繁体   English   中英

如何编写多线程代码以加快繁重的重复任务?

[英]How do I code multithreading to speed up heavy, repetitive task?

我有一个swing应用程序,启动起来很慢,因为它必须将一千张图片加载到GUI中。 启动需要10秒钟。

它是一个单线程应用程序,如何编码多线程以加快任务速度? 以下代码处于1000次迭代的for循环中。

    ImageIcon icon = new ImageIcon(Files.readAllBytes(coverFile.toPath()));
    // ImageIcon icon = createImageIcon(coverFile);
    JLabel label = null;
    if (coverCount % 2 == 0) {
     label = createLabel(coverFile, movieFile, icon, SwingConstants.LEFT);
    } else {
     label = createLabel(coverFile, movieFile, icon, SwingConstants.CENTER);
    }
    box.add(label);

图像被依次装入并放入盒子中。 我想做多线程有两个困难

  1. 线程如何将值返回给父对象
  2. 如何实现无阻塞的回调,从而将图像顺序添加到框中

谢谢。

线程如何将值返回给父对象

使用回叫机制。 对于Swing,这意味着使用SwingWorker并通过worker的done()方法或通过向该worker添加PropertyChangeListener来通知GUI线程完成情况,以侦听该工人的“ state”属性,以了解何时更改为SwingWorker.StateValue.DONE

如何实现无阻塞的回调,从而将图像顺序添加到框中

SwingWorker具有一个发布/处理方法对,该对允许通过publish方法从后台线程顺序发送数据,然后在process方法内的事件线程上顺序处理数据。 这需要使用SwingWorker<VOID, Image>SwingWorker<VOID, Icon>或类似的东西,第二个通用参数指示通过此机制发送的对象的类型。

例如:

public class MyWorker extends SwingWorker<Void, Icon> {
    @Override
    protected Void doInBackground() throws Exception {
        boolean done = false;
        while (!done) {
            // TODO: create some_input here -- possibly a URL or File
            Image image = ImageIO.read(some_input);
            Icon icon = new ImageIcon(image);
            publish(icon);

            // TODO: set done here to true when we ARE done
        }
        return null;
    }

    @Override
    protected void process(List<Icon> chunks) {
        for (Icon icon : chunks) {
            // do something with the icon here
            // on the event thread
        }
    }
}

并在GUI中使用它:

// may need constructor to pass GUI into worker
final MyWorker myWorker = new MyWorker();
myWorker.addPropertyChangeListener(evt -> {
    if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
        // We're done!
        // call get to trap errors
        try {
            myWorker.get();
        } catch (InterruptedException | ExecutionException e) {
            // TODO: real error handling needed here
            e.printStackTrace();
        }
    }
});
myWorker.execute(); // start worker in a background thread

有关Swing并发的更多信息,请查看课程:Swing中的并发

多线程将加快应用程序的速度,但是我认为执行延迟加载是更好的方法(您可以同时执行)。 您不能同时显示所有这些图像,因此建议您加载在开始时可见的图像,然后根据需要加载图像,这将极大地提高性能并减少内存/资源的使用。

如果您确实要加载全部1000张图像:

使用一个后台线程就足够了,这样就不会降低主Swing Event循环线程的速度。

创建一个实现可运行的自定义类,该类具有对所有上下文的引用以完成此工作。 像这样:

public static class IconLoader implements Runnable{
    private List<File> movies;
    private File coverFile;
    private JPanel box;
    public IconLoader(JPanel box, File coverFile, List<File> movies) {
        this.box = box;
        this.coverFile = coverFile;
        this.movies = movies;
    }

    @Override
    public void run() {

        for(int coverCount=0;coverCount<movies.size();coverCount++) {
            try {
                final JLabel label;
                File movieFile = movies.get(coverCount);
                ImageIcon icon = new ImageIcon(Files.readAllBytes(coverFile.toPath()));
                // ImageIcon icon = createImageIcon(coverFile);

                if (coverCount % 2 == 0) {
                 label = createLabel(coverFile, movieFile, icon, SwingConstants.LEFT);
                } else {
                 label = createLabel(coverFile, movieFile, icon, SwingConstants.CENTER);
                }

                SwingUtilities.invokeLater( new Runnable() {
                    @Override
                    public void run() {
                        box.add(label);
                    }
                });
            }catch(IOException e) {
                e.printStackTrace();
            }
        }
    }

    private JLabel createLabel(File coverFile, File movieFile, ImageIcon icon, int direction) {
        //Create the label and return
        return null;
    }
}

然后,通过将可运行项传递给新线程并启动线程,在应用初始化期间开始加载过程。 像这样:

new Thread( new IconLoader(box, coverFile, movies) ).start();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM