我想运行多个线程并在我的main方法结束时加入它们,所以我可以知道它们何时完成并处理一些信息。
我不想将我的线程放在一个数组中并逐个执行join(),因为join是一个阻塞方法,我会在主线程中等待一些线程仍在运行,而其他线程可能有已经完成,没有可能知道。
我已经考虑过为我的线程实现一个观察者模式的可能性:一个带有update()方法的接口,一个从线程扩展的抽象类(或实现runnable),带有set和get方法,用于监听器和一个类启动我所有的线程都在等待他们完成。
如果我的理解是正确的,观察者不会阻塞特定的连接()中的线程。相反,它将以某种方式等待,直到线程调用update()方法来执行操作。在这种情况下,应在线程完成后立即调用update()。
我对如何实现这一点毫无头绪。我尝试过类似的模型,但我不知道如何使用观察者/监听器唤醒/阻止我的主线程。我已经将这个旧帖子用作模板:How to know if other threads have finished?但是一旦线程调用update()方法,我找不到唤醒main方法的方法。将只为所有线程实例化一个观察者对象。
你能想到一种方法来使用观察者模式来等待所有线程完成而不会阻塞main一个接一个的join()调用吗?任何其他解决这个问题的建议将不胜感激。提前谢谢。
答案 0 :(得分:6)
Java已经有了这样做的API:CompletionService
。
将新异步任务的生成与已完成任务的结果消耗分离的服务。生产者提交执行任务。消费者完成任务并按照他们完成的顺序处理结果。
答案 1 :(得分:5)
我认为你不需要观察者模式。线程等待任何结果将不得不阻止,否则它将完成或循环无穷大。您可以使用某种BlockingQueue - 生产者将计算结果添加到阻塞队列(然后完成),主线程将在没有任何结果时接收这些结果阻塞..
好消息,它已经实施了:) CompletionService
和Executors framework
的良好机制。试试这个:
private static final int NTHREADS = 5;
private static final int NTASKS = 100;
private static final ExecutorService exec = Executors.newFixedThreadPool(NTHREADS);
public static void main(String[] args) throws InterruptedException {
final CompletionService<Long> ecs = new ExecutorCompletionService<Long>(exec);
for (final int i = 0; i < NTASKS ; ++i) {
Callable<Long> task = new Callable<Long>() {
@Override
public Long call() throws Exception {
return i;
}
};
ecs.submit(task);
}
for (int i = 0; i < NTASKS; ++i) {
try {
long l = ecs.take().get();
System.out.print(l);
} catch (ExecutionException e) {
e.getCause().printStackTrace();
}
}
exec.shutdownNow();
exec.awaitTermination(50, TimeUnit.MILLISECONDS);
}
答案 2 :(得分:0)
听起来像是在寻找Counting Completion Service最近讨论的Dr. Heinz M. Kabutz之类的内容。