运行ExecutorService里面的SwingWorker一个好的做法? [英] Is running a ExecutorService inside a SwingWorker a good practice?

查看:116
本文介绍了运行ExecutorService里面的SwingWorker一个好的做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码:

        SwingWorker<Void, Void> sworker = new SwingWorker<Void, Void>() {

        @Override
        protected Void doInBackground() throws Exception {
            ExecutorService executor = Executors.newFixedThreadPool(5);
            try {
                for (int j = 0; j < 5; j++) {
                    Callable<Object> worker = new MyCallableImpl();
                    Future<Object> future = executor.submit(worker); 
                    array[j] = future.get();
                }
            } catch (InterruptedException e) {
                // some code here
            } catch (ExecutionException e) {
                // some code here
            }
                // some code here
            executor.shutdown();
            return null;
        }

    };
    sworker.execute();

正如我在标题中说的:这是一个很好的做法,在doInBackground()方法中调用ExecutorService SwingWorker?它适用于我(JDK1.7),GUI不会被阻塞,并且执行器池中的多个线程正在后台运行,但仍然有一些疑问...

As I said in the title: is this a good practice to invoke ExecutorService inside doInBackground() method of SwingWorker? It works for me (JDK1.7), GUI is not blocked and multiple threads from Executor pool are running in background, but still I have some doubts...

推荐答案

进一步回应。这没有意义,因为你的执行实际上是单线程的。 doInBackground 将提交给执行者,并等待该单个任务完成,然后提交另一个任务。

To further mre's response. It doesn't make sense because your execution is actually single-threaded. The doInBackground will submit to the executor and wait for that single task to complete then submit another.

您应该提交同样的方式,但将返回的未来存储在某种类型的列表中

You should submit the same way, but store the returned Futures in a List of some sort then get on each one of them after all tasks have been submitted.

我不太在意 doInBackground 提交这些工作与mre异步。如果你试图提交一些任务,并且只有N在任何给定的时间提交,你绝对不应该通过 SwingWorker.doInBackground 。使用 ExectorService + SwingUtilities.invokeLater 我认为是更好的方法。

I don't as much mind the doInBackground to submit these jobs asynchronously as mre does. If you are trying to submit a number of tasks and have only N submitted at any given time you definitely shouldn't do this through SwingWorker.doInBackground. Using an ExectorService + SwingUtilities.invokeLater I think is the better way.

为了澄清任何混淆, invokeLater 只能在ExecutorService中的任务完成时使用所有它需要做的是更新UI组件。

And just to clarify any confusion, invokeLater should only be used here when the task within the ExecutorService is complete and all it needs to do is update the UI component.

编辑:解决您的评论的示例

Example to address your comment

protected Void doInBackground() throws Exception {
    ExecutorService executor = Executors.newFixedThreadPool(5);
    List<Future> futures = ...;
    try {
        for (int j = 0; j < 5; j++) {
            Callable<Object> worker = new MyCallableImpl();
            futures.add(executor.submit(new Callable<Object>(){
                 public Object call(){
                    //expensive time consuming operation
                    final String result = ...;//result from consuming operation
                    SwingUtilities.invokeLater(new Runnable(){
                        public void run(){
                             jLabel.setText(result);
                        }
                    });
                    return new Object();
                 }
            ));
        }
        for(Future<Object> f :futures)f.get();
        executor.shutdown();
    return null;
}

注意 invokeLater 做完一个简单的更新?这不应该导致您的EDT冻结。

Notice how the invokeLater is done to do a simple update? That should not cause your EDT to freeze.

这篇关于运行ExecutorService里面的SwingWorker一个好的做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆