2014-01-13 60 views
0

我觉得我的Java并发知识越来越生疏,我试图找出为什么线程池不会在下面的代码接受更多的任务:线程池不接受新的任务

ExecutorService e = Executors.newFixedThreadPool(aNumber); 

// Task 1 
for (int i=0; i<n; i++) 
    e.submit(new aRunnable()); 
while (!e.isTerminated()); 
System.out.println("Task 1 done"); 

// Task 2 
for (int i=0; i<n; i++) 
    e.submit(new anotherRunnable()); 
while (!e.isTerminated()); 
System.out.println("Task 2 done"); 

它从来没有启动任务2,当任务1中的最后一个任务运行时,线程“冻结”,就像它正在等待其他任务完成一样。

怎么了?

+0

推荐阅读:http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ – JVMATL

回答

4

它永远不会启动任务2,当任务1中的最后一个任务运行时,线程“冻结”,就像它正在等待其他任务完成一样。

它正在等待。 ExecutorService.isTerminated()等待线程池任务完成池已关闭。既然你从未称过e.shutdown();你的循环将永远旋转。引用来自ExecutorService javadocs

如果所有任务在关闭后都完成,则返回true。请注意,除非shutdown或shutdownNow先被调用,否则isTerminated从来就不是真的。

你还没有关闭服务,所以永远不会是真的。一般而言,像这样循环的任何东西都是极其糟糕的模式。通常我们使用e.awaitTermination(...),但是,只有在您调用e.shutdown();之后。而且您不想关闭ExecutorService,因为您将要向其提交更多任务。

如果您想等待所有任务完成,然后提交更多任务,我会执行类似以下操作的任务,并在Future上调用get(),这些任务是从第一批提交任务返回的。喜欢的东西:

List<Future> futures = new ArrayList<Future>(); 
for (int i=0; i<n; i++) { 
    futures.add(e.submit(new aRunnable())); 
} 
// now go back and wait for all of those tasks to finish 
for (Future future : futures) { 
    future.get(); 
} 
// now you can go forward and submit other tasks to the thread-pool 
0

如果你想知道当一个特定的任务完成时,使用一个ExecutorService,它会返回一个Future <>(你可以用它来获得一个特定的工作状态的手柄) - 执行者本身在你关闭之前不会终止。想想像'批队列'或'协处理器'这样的执行者等着你在斗中投掷一些工作。

更新:格雷比我回答得好得多 - 见他的帖子。 - (人们怎么快速打字?)