Java 程序挂起时线程不';不要终止
我有这种奇怪的行为。我的程序挂起,即使我正在设置强制终止它的时间。有人能指出这种奇怪的行为是什么吗 这是我的代码,我从这里开始线程Java 程序挂起时线程不';不要终止,java,multithreading,Java,Multithreading,我有这种奇怪的行为。我的程序挂起,即使我正在设置强制终止它的时间。有人能指出这种奇怪的行为是什么吗 这是我的代码,我从这里开始线程 protected void pendingTaskStarter() throws Exception { ExecutorService service = Executors.newFixedThreadPool(maxThreadNum); ArrayList<Future<Runnable>> futures = n
protected void pendingTaskStarter() throws Exception {
ExecutorService service = Executors.newFixedThreadPool(maxThreadNum);
ArrayList<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();
System.out.println("max thread num: " + maxThreadNum);
for(int i=0;i<maxThreadNum;i++){
Thread t = new PendingTaskConsumer();
Future<?> f=service.submit(t);
futures.add((Future<Runnable>) f);
}
for (Future<?> future:futures) {
future.get(5l,TimeUnit.MINUTES); // maximum thread's life is 5min (5l <-- 5 in long )
}
service.shutdownNow();
}
该程序运行在
Linux(Ubuntu)
上,并使用openjdk-7-jdk后台(1.7版)
很好。。。似乎缺少正确的异常处理
/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result, if available.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
* @throws **TimeoutException if the wait timed out**
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
如果您呼叫future.get(5l,TimeUnit.MINUTES)代码>过期,然后抛出一个异常
,并且您的服务
永远不会关闭
因此(可以假设)它的内部线程仍在运行,至少是执行长时间运行的任务的线程)。看到这些是非守护进程线程(您必须自定义执行器的ThreadFactory
),这些挂起的线程会阻止JVM关闭
如果您希望强制终止任务,您可以:
将可运行任务设计为响应线程.isInterrupted()
,并在看到这一点时退出。(现在关闭的实际效果是设置执行器的线程的中断标志)
如果您不能(因为您的线程被某个库中不侦听中断的方法阻塞),那么拥有dameon线程似乎是唯一的选择
但无论如何,我会将执行器的关闭放在更早的地方,或者放在finally
子句中。正如@GPI在其回答中已经指出的那样,如果您的任务没有通过thread.interrupt()响应线程中断,取消将无法正常工作。看到或看到
但是,即使您的任务在线程被中断时没有立即停止(=设置了中断标志),您也可以使方法超时。只是不要通过调用未来的方法的每一个get()
方法来听任务完成!这是没有必要的,因为你对他们的结果并不感兴趣。只需关闭您的ExecutorService
,等待其终止
protected void pendingTaskStarter() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(maxThreadNum);
for (int i = 0; i < maxThreadNum; i++) {
service.submit(new PendingTaskConsumer());
}
// Shutdown service.
// This will continue to process already submitted tasks.
service.shutdown();
try {
// wait at least 5 minutes for the tasks to complete
if (!service.awaitTermination(5, TimeUnit.MINUTES)) {
// still not done yet -> force shutdown
// this will interrupt currently running tasks.
service.shutdownNow();
}
} catch (InterruptedException ex) {
// someone interrupted this thread. Shutdown tasks immediately
service.shutdownNow();
// propagate exception
throw ex;
}
}
protectedvoid pendingTaskStarter()引发中断异常{
ExecutorService=Executors.newFixedThreadPool(maxThreadNum);
对于(int i=0;i强制关机
//这将中断当前正在运行的任务。
service.shutdownNow();
}
}捕获(中断异常例外){
//有人中断了此线程。请立即关闭任务
service.shutdownNow();
//传播异常
掷骰子;
}
}
那么这里发生了什么
- 首先,提交所有任务
- 然后对执行器服务调用
shutdown()
。请注意,该服务将被删除
- 现在,我们通过调用超时5分钟来等待服务终止。如果此方法返回
true
,这意味着服务已在时间内终止,则一切正常,我们已完成。但如果在5分钟后返回false
,则表示服务仍在运行,因为有些任务需要更多时间才能完成
- 在这种情况下,我们通过调用
shutdownNow()
立即关闭服务。请注意,此方法不会阻塞!它只是试图取消所有正在运行的任务,通常是中断当前正在执行这些任务的线程。这就是为什么您的任务应该正确响应线程中断!如果他们不这样做,中断线程将毫无效果李>
- 无论
shutdownow
是否成功,我们都已完成,不再等待。因此,可能仍有一些任务正在运行,因为它们在线程中断时不会做出反应(通常是因为任务未正确执行或是故意不间断地执行)。但我们根本不在乎
- 请注意异常处理程序:当另一个线程在方法
waittermination
中等待时中断调用我们方法的线程时,将抛出InterruptedException
。我们通过关闭服务并重新抛出异常来处理它!这是一件好事,使我们的方法成为一个可以自行取消的长时间运行的操作李>
该程序预计运行多长时间?您等待它完成的时间有多长?我在这一层上有一个API,如果这个程序没有在20分钟内终止,那么它会重新启动这个程序正在运行的机器(1)为什么PendingTaskConsumer
是从线程
派生出来的?它不是一个线程,而是由ExecutorService
维护的另一个线程执行的任务。(2) PendingTaskConsumer()
是方法调用吗?如果否,则可能缺少new
关键字。@isnot2bad PendingTaskConsumer is class,在问题中,我没有在前面添加关键字“new”@nafas OK。但是你仍然不应该从这里的线程中派生PendingConsumer
只是一个Runnable
或Callable
,而不是一个线程本身!(线程由执行器内部管理!)非常有趣的伙伴,我从未考虑过这一点。但我会试试,让你知道。这是一个非常清楚的解释。我喜欢你提到的那一部分,没有必要跟踪未来。我会试试,让你知道我会非常惊讶的,它成功了。我相信我的前任;成功了。即使线程没有被终止。我摆脱了那种方法。然后,一旦其他一切都完成了,我所需要做的就是添加Sy
protected void pendingTaskStarter() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(maxThreadNum);
for (int i = 0; i < maxThreadNum; i++) {
service.submit(new PendingTaskConsumer());
}
// Shutdown service.
// This will continue to process already submitted tasks.
service.shutdown();
try {
// wait at least 5 minutes for the tasks to complete
if (!service.awaitTermination(5, TimeUnit.MINUTES)) {
// still not done yet -> force shutdown
// this will interrupt currently running tasks.
service.shutdownNow();
}
} catch (InterruptedException ex) {
// someone interrupted this thread. Shutdown tasks immediately
service.shutdownNow();
// propagate exception
throw ex;
}
}