Java - 如何告诉所有子线程完成
Java - How to tell all subthreads are done
我想同时 运行 几个任务,所以我有一个如下所示的代码:
for(final Task task : tasks){
(new Thread(){public void run(){
task.run(args);
}}).start();
我如何知道所有任务何时完成(任务的数量可能会有所不同)以便我可以 运行 只有在所有任务都完成后才能做一些事情?
System.out.println("All tasks are finished");
创建线程时只需将每个线程添加到列表中即可:
LinkedList<Thread> threads = new LinkedList<>();
当你创建一个新线程时:
Thread t = new Thread() {
public void run() {
task.run(args);
}
}
threads.add(t);
然后您可以检查您列表中的每个线程,看它是否已完成:
boolean allFinished = true;
for (Thread t : threads) {
if (t.isAlive()) {
allFinished = false;
break;
}
}
有关检查线程是否已完成的更多信息,请参阅此 link:
How to know if other threads have finished?
这个问题的关键点是,如果你想稍后检查线程,你必须在某处存储它们的列表(或数组等)。
不要显式创建线程,而是将您的 Runnable 提交给 ExecutorService,然后调用它的 shutdown and awaitTermination 方法:
ExecutorService executor = Executors.newFixedThreadPool(tasks.size());
for (final Task task : tasks) {
executor.submit(new Runnable() {
@Override
public void run() {
task.run(args);
}
});
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLSECONDS);
另一种方法是使用 Future interface. Doing it this way gives you some other nifty features. See this 来举例。
您还可以使用 CountDownLatch 来指示线程是否完成。参见 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html
像这样:
public static class Task {
void run(String args[]) {
System.out.println("Hello");
}
}
public static void main(String[] args) {
List<Task> tasks = Arrays.asList(new Task(), new Task(), new Task());
CountDownLatch doneSignal = new CountDownLatch(tasks.size());
for(final Task task : tasks) {
(new Thread() {
public void run(){
task.run(args);
}
}).start();
doneSignal.countDown(); //counts latch down by one
}
//A
new Thread() {
public void run() {
try {
doneSignal.await(); //blocks until latch counted down to zero
System.out.println("All tasks completed");
} catch(Exception e) {
System.out.println("Warning: Thread interrupted.");
}
}
}.start();
}
每个任务线程在完成时都会对锁存器进行倒数计数。在//A 处创建的线程将等待直到锁存器倒计时为零。只有这样,才会打印 "All tasks completed" 语句。所以基本上 doneSignal.await() 之后的语句只会在所有线程完成后执行。
使用 CyclicBarrier ,例如:
http://tutorials.jenkov.com/java-util-concurrent/cyclicbarrier.html
一个较短的版本是使用 parallelStream
tasks.parallelStream().forEach(t -> t.run(args));
这将 运行 所有任务,使用您拥有的所有 CPU(如果您有足够的任务)并等待全部完成。
我想同时 运行 几个任务,所以我有一个如下所示的代码:
for(final Task task : tasks){
(new Thread(){public void run(){
task.run(args);
}}).start();
我如何知道所有任务何时完成(任务的数量可能会有所不同)以便我可以 运行 只有在所有任务都完成后才能做一些事情?
System.out.println("All tasks are finished");
创建线程时只需将每个线程添加到列表中即可:
LinkedList<Thread> threads = new LinkedList<>();
当你创建一个新线程时:
Thread t = new Thread() {
public void run() {
task.run(args);
}
}
threads.add(t);
然后您可以检查您列表中的每个线程,看它是否已完成:
boolean allFinished = true;
for (Thread t : threads) {
if (t.isAlive()) {
allFinished = false;
break;
}
}
有关检查线程是否已完成的更多信息,请参阅此 link:
How to know if other threads have finished?
这个问题的关键点是,如果你想稍后检查线程,你必须在某处存储它们的列表(或数组等)。
不要显式创建线程,而是将您的 Runnable 提交给 ExecutorService,然后调用它的 shutdown and awaitTermination 方法:
ExecutorService executor = Executors.newFixedThreadPool(tasks.size());
for (final Task task : tasks) {
executor.submit(new Runnable() {
@Override
public void run() {
task.run(args);
}
});
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLSECONDS);
另一种方法是使用 Future interface. Doing it this way gives you some other nifty features. See this 来举例。
您还可以使用 CountDownLatch 来指示线程是否完成。参见 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html
像这样:
public static class Task {
void run(String args[]) {
System.out.println("Hello");
}
}
public static void main(String[] args) {
List<Task> tasks = Arrays.asList(new Task(), new Task(), new Task());
CountDownLatch doneSignal = new CountDownLatch(tasks.size());
for(final Task task : tasks) {
(new Thread() {
public void run(){
task.run(args);
}
}).start();
doneSignal.countDown(); //counts latch down by one
}
//A
new Thread() {
public void run() {
try {
doneSignal.await(); //blocks until latch counted down to zero
System.out.println("All tasks completed");
} catch(Exception e) {
System.out.println("Warning: Thread interrupted.");
}
}
}.start();
}
每个任务线程在完成时都会对锁存器进行倒数计数。在//A 处创建的线程将等待直到锁存器倒计时为零。只有这样,才会打印 "All tasks completed" 语句。所以基本上 doneSignal.await() 之后的语句只会在所有线程完成后执行。
使用 CyclicBarrier ,例如: http://tutorials.jenkov.com/java-util-concurrent/cyclicbarrier.html
一个较短的版本是使用 parallelStream
tasks.parallelStream().forEach(t -> t.run(args));
这将 运行 所有任务,使用您拥有的所有 CPU(如果您有足够的任务)并等待全部完成。