我正在学习如何使用ExecutorService
在Java中使用线程池,这是我正在研究的一个例子:
public class Example {
static class WorkerThread implements Runnable {
private String command;
public WorkerThread(String s) {
this.command = s;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Start. Command = " + command);
processCommand();
System.out.println(Thread.currentThread().getName() + " End.");
}
private void processCommand() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return this.command;
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("" + i);
executor.execute(worker);
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.SECONDS);
// while (!executor.isTerminated()) {
// }
System.out.println("Finished all threads");
}
}
我有两个问题:
如果我使用ExecutorService
或awaitTermination()
,我应该如何等待isTerminated()
的终止(有人建议后者是错误的做法) )?
Runnable
是否已正确添加到执行程序中,还是应将submit()
与Future<T>
回调一起使用?
这可能取决于具体情况,所以请您解释(对于这两个问题)我应该何时使用所提到的每个解决方案。
答案 0 :(得分:1)
实现它的几种方法:
(a)在if fraction.numerator == 1:
break
内拨打awaitTermination(long someTime, TimeUnit ....)
。
(b)将所有可调用的内容存储在Collection对象中并调用while (!executor.isTerminated())
。这将等到所有任务由执行者服务完成。
答案 1 :(得分:1)
这个程序没有等待线程终止,JVM正在进行等待:我得到的输出是:
pool-1-thread-1 Start. Command = 0
pool-1-thread-2 Start. Command = 1
pool-1-thread-3 Start. Command = 2
pool-1-thread-4 Start. Command = 3
pool-1-thread-5 Start. Command = 4
Finished all threads
pool-1-thread-2 End.
pool-1-thread-1 End.
pool-1-thread-4 End.
pool-1-thread-1 Start. Command = 5
pool-1-thread-3 End.
pool-1-thread-2 Start. Command = 7
pool-1-thread-5 End.
pool-1-thread-4 Start. Command = 6
pool-1-thread-5 Start. Command = 9
pool-1-thread-3 Start. Command = 8
pool-1-thread-3 End.
pool-1-thread-5 End.
pool-1-thread-4 End.
pool-1-thread-1 End.
pool-1-thread-2 End.
您会注意到Finished all threads
不在底部。如果要等待所有线程完成,请使用:
public class Example {
static class WorkerThread implements Runnable {
private String command;
public WorkerThread(String s) {
this.command = s;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Start. Command = " + command);
processCommand();
System.out.println(Thread.currentThread().getName() + " End.");
}
private void processCommand() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return this.command;
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Callable<Object>> tasks = new ArrayList<Callable<Object>>();
for (int i = 0; i < 10; i++) {
tasks.add(Executors.callable(new WorkerThread("" + i)));
}
executor.invokeAll(tasks);
System.out.println("Finished all threads");
// this merely terminates the ExecutorService, otherwise the JVM will never close.
executor.shutdown();
executor.awaitTermination(10L, TimeUnit.SECONDS);
}
}
您会注意到正确的输出:
pool-1-thread-1 Start. Command = 0
pool-1-thread-5 Start. Command = 4
pool-1-thread-4 Start. Command = 3
pool-1-thread-3 Start. Command = 2
pool-1-thread-2 Start. Command = 1
pool-1-thread-3 End.
pool-1-thread-1 End.
pool-1-thread-5 End.
pool-1-thread-3 Start. Command = 5
pool-1-thread-2 End.
pool-1-thread-4 End.
pool-1-thread-2 Start. Command = 8
pool-1-thread-1 Start. Command = 7
pool-1-thread-5 Start. Command = 6
pool-1-thread-4 Start. Command = 9
pool-1-thread-1 End.
pool-1-thread-4 End.
pool-1-thread-3 End.
pool-1-thread-5 End.
pool-1-thread-2 End.
Finished all threads
答案 2 :(得分:1)
1.如果我使用awaitTermination()或isTerminated(),我应该如何等待ExecutorService的终止(有人建议后者是一种错误的方法)?
awaitTermination()
之后使用shutdown()
OR invokeAll()
OR CountDownLatch
详细了解相关的SE问题:
How to wait for all threads to finish, using ExecutorService?
ExecutorService, how to wait for all tasks to finish
Waiting for all the threads to finish before shutting down the Executors
2. Runnables是否已正确添加到执行程序中,还是应该将submit()与Future回调一起使用?
Runnable
Callable
如果您使用submit()
,则会在框架中隐藏异常,您必须正确处理异常。
查看相关的SE问题:
Choose between ExecutorService's submit and ExecutorService's execute
difference between executor.submit and executor.execute in this code in Java?