首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何正确扩展FutureTask

如何正确扩展FutureTask
EN

Stack Overflow用户
提问于 2013-02-27 13:04:44
回答 2查看 2.5K关注 0票数 0

在编写计算量大的应用程序时,我尝试使用SwingWorker类将负载分散到多个CPU核心。然而,事实证明,这类人的行为有些奇怪:似乎只有一个核心被利用。

在搜索互联网时,我在这个网站上找到了一个很好的答案(参见Swingworker实例不并发运行,由user268396回答),这个答案--除了问题的原因--还提到了一个可能的解决方案:

要解决这个问题,您可以使用ExecutorService并在其上发布FutureTasks。这些将提供99%的SwingWorker API (SwingWorker是FutureTask派生程序),您所要做的就是正确地设置您的执行器。

作为一个Java初学者,我不太清楚如何正确地做到这一点。我不仅需要将一些初始数据传递给FutureTask对象,还需要获得与SwingWorker类似的结果。因此,任何示例代码都将是非常感谢的。

nvx

====================编辑====================

在实现了实现可调用的FutureTask中提到的简单而优雅的解决方案之后,又出现了另一个问题。如果我使用ExecutorService来创建单独的线程,那么如何在线程运行完成后执行特定的代码?

我试图覆盖FutureTask对象的done() (请参阅下面的代码),但我认为应该在应用程序的事件调度线程(EDT)中执行“显示结果”位(或任何与GUI相关的内容)。因此:我如何向EDT提交可运行的?

代码语言:javascript
复制
package multicoretest;

import java.util.concurrent.*;

public class MultiCoreTest {

    static int coresToBeUsed = 4;
    static Future[] futures = new Future[coresToBeUsed];

    public static void main(String[] args) {
        ExecutorService execSvc = Executors.newFixedThreadPool(coresToBeUsed);
        for (int i = 0; i < coresToBeUsed; i++) {
            futures[i] = execSvc.submit(new Worker(i));
        }
        execSvc.shutdown();

        // I do not want to block the thread (so that users can
        // e.g. terminate the computation via GUI)
        //execSvc.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

    }

    static class Worker implements Callable<String> {

        private final FutureTask<String> futureTask;
        private final int workerIdx;

        public Worker(int idx) {
            workerIdx = idx;
            futureTask = new FutureTask<String>(this) {
                @Override
                protected void done() {
                    Runnable r = new Runnable() {
                        @Override
                        public void run() {
                            showResults(workerIdx);
                        }
                    };

                    r.run(); // Does not work => how do I submit the runnable
                             // to the application's event dispatch thread?

                }
            };
        }

        @Override
        public String call() throws Exception {
            String s = "";
            for (int i = 0; i < 2e4; i++) {
                s += String.valueOf(i) + " ";
            }
            return s;
        }

        final String get() throws InterruptedException, ExecutionException {
            return futureTask.get();
        }

        void showResults(int idx) {
            try {
                System.out.println("Worker " + idx + ":" +
                        (String)futures[idx].get());
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-28 13:35:14

以下几点:

  • 您很少需要直接使用FutureTask,只需实现可调用或可运行并将实例提交给执行器即可。
  • 为了在完成之后更新gui,作为run()/call()方法的最后一步,使用SwingUtilities.invokeLater()与代码一起更新ui。

注意,您仍然可以使用SwingWorker,而不是调用execute(),而是将SwingWorker提交给您的执行器。

如果在更新gui之前完成所有线程时,需要一起处理所有结果,那么我建议:

  • 让每个工作人员将其结果保存到线程安全共享列表中
  • 最后一个将结果添加到列表中的工作人员应该完成后处理工作。
  • 然后,完成后处理工作的工作人员应该调用具有最终结果的SwingUtilities.invokeLater()
票数 2
EN

Stack Overflow用户

发布于 2013-02-27 13:10:22

我试图利用SwingWorker类将负载分散到多个CPU核心。然而,事实证明,这类人的行为有些奇怪:似乎只有一个核心被利用。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15112836

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档