运行ExecutorService里面的SwingWorker一个好的做法? [英] Is running a ExecutorService inside a SwingWorker a good practice?
问题描述
请考虑以下代码:
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 Future
s 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屋!