[英]How to properly extend FutureTask
While coding a computation-heavy application, I tried to make use of the SwingWorker class to spread the load to multiple CPU cores. 在编写计算繁重的应用程序时,我尝试利用SwingWorker类将负载分散到多个CPU内核。 However, behaviour of this class proved to be somewhat strange: only one core seemed to be utilized.
但是,该类的行为被证明有些奇怪:似乎只使用了一个核心。
When searching the internet, I found an excellent answer on this web (see Swingworker instances not running concurrently , answer by user268396) which -- in addition to the cause of the problem -- also mentions a possible solution: 在Internet上搜索时,我在此Web上找到了一个很好的答案(请参阅Swingworker实例未同时运行 ,由user268396回答),除了引起问题的原因外,还提到了可能的解决方案:
What you can do to get around this is use an ExecutorService and post FutureTasks on it.
要解决此问题,您可以使用ExecutorService并在其上发布FutureTasks。 These will provide 99% of the SwingWorker API (SwingWorker is a FutureTask derivative), all you have to do is set up your Executor properly.
这些将提供99%的SwingWorker API(SwingWorker是FutureTask的派生产品),您要做的就是正确设置执行器。
Being a Java beginner, I am not entirely sure how to do this properly. 作为Java初学者,我不太确定如何正确执行此操作。 Not only that I need to pass some initial data to the FutureTask objects, I also need to get the results back similarly as with SwingWorker.
我不仅需要将一些初始数据传递给FutureTask对象,而且还需要像使用SwingWorker一样返回结果。 Any example code would therefore be much appreciated.
因此,将非常感谢任何示例代码。
nvx NVX
==================== EDIT ==================== ===================编辑====================
After implementing the simple yet elegant solution mentioned in FutureTask that implements Callable , another issue has come up. 在实现FutureTask中提到的实现Callable的简单而优雅的解决方案之后,又出现了另一个问题。 If I use an
ExecutorService
to create individual threads, how do I execute specific code after a thread finished running? 如果我使用
ExecutorService
创建单个线程,那么在线程运行完毕后如何执行特定代码?
I tried to override done() of the FutureTask
object (see the code below) but I guess that the "show results" bit (or any GUI related stuff for that matter) should be done in the application's event dispatch thread (EDT). 我试图覆盖
FutureTask
对象的done()(请参见下面的代码),但是我猜应该在应用程序的事件分发线程(EDT)中完成“显示结果”位(或任何与此GUI相关的工作)。 Therefore: how do I submit the runnable to the EDT? 因此:如何将可运行文件提交给EDT?
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());
}
}
}
}
I tried to make use of the SwingWorker class to spread the load to multiple CPU cores.
我试图利用SwingWorker类将负载分散到多个CPU内核。 However, behaviour of this class proved to be somewhat strange: only one core seemed to be utilized.
但是,该类的行为被证明有些奇怪:似乎只使用了一个核心。
no idea without posting an SSCCE , short, runnable, compilable, 不发布SSCCE就不知道了,简短,可运行,可编译,
SwingWorker
is designated creating Workers Thread
for Swing GUI, more in this thread SwingWorker
被指定为Swing GUI创建Workers Thread
, 更多有关此线程
A couple of points: 要点:
run()
/ call()
method, use SwingUtilities.invokeLater()
with the code to update the ui. run()
/ call()
方法的最后一步,将SwingUtilities.invokeLater()
与代码一起使用以更新ui。 Note, you can still use SwingWorker
, just, instead of calling execute()
, submit the SwingWorker to your Executor instead. 注意,您仍然可以使用
SwingWorker
,而不是调用execute()
,而不是将SwingWorker提交给您的执行器。
if you need to process all results together when all threads are done before updating the gui, then i would suggest: 如果您需要在更新gui之前完成所有线程时一起处理所有结果,那么我建议:
SwingUtilities.invokeLater()
with the final results SwingUtilities.invokeLater()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.