我有一个运行多个线程的系统 - 我的主线程只是检查是否有要完成的工作,如果有一些,它会调用将执行它的子线程(notifyAll()
)。之后,子线程只有wait()
,直到有一些新任务。
实际上,线程系统运行可靠,但经过较长的运行时间(3-5h)后,某些子线程会在没有警告或错误的情况下死亡。他们只是一个接一个地退出 - 但是再次只有2个小时的时间范围。我已经使用jconsole来检查这种现象,哪些线程正在运行以及它们是如何消失的。
此外,主线程每秒执行一次,但子线程主要是wait()
并且根本不常用(因为测试环境中没有那么多任务)。
我能想到的唯一原因是,JVM会关闭子线程,因为它们通常不够用?
我非常感谢你的帮助!
P.S。所有线程都没有定义为守护进程,主线程工作正常!
感谢您的回答,但我确实使用了这个循环。
public void addTask (Task in_task) throws InterruptedException {
synchronized (tasks) {
while (tasks.size() == MAXIMUM_NUMBER_OF_TASKS) {
tasks.wait();
}
tasks.offer(in_task);
tasks.notifyAll();
}
}
我使用这个循环,因此只会执行一些特殊的任务。
答案 0 :(得分:5)
Object.wait()的文档说:
在一个参数版本中,中断和虚假唤醒是可能的,并且此方法应始终在循环中使用:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
也许你没有遵循这个建议并得到虚假的唤醒或中断?
答案 1 :(得分:2)
您可以使用java.util.concurrent.ThreadPoolExecutor
而不是编写自己的多线程任务执行解决方案。无论你是否能够修复这个bug,这都可能是一个好主意。
答案 2 :(得分:1)
我建议使用其中一个Executors
来管理您的任务。您在其中一个子线程中丢失可能的错误或异常的可能性较小,因此它应该可以帮助您调试程序。当您调用Future
时,子线程中发生的任何异常都将存储在ExecutionException
对象中,并作为Future#get()
重新生成。
List<Future<Void>> taskResults = new ArrayList<Future<Void>>();
ExecutorService es = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
while(!finished){
//say you wait (blocking) for a new task here
Callable<Void> task = getNextTask();
//put the task into the pool
Future<Void> result = es.submit(task);
taskResults.add(result);
}
//3 hours later, set `finished` to true
//at the end check that no exceptions were thrown
for(Future<Void> result : taskResults){
try{
result.get();
}catch(ExecutionException e){
//there was an error
e.getCause().printStackTrace();
}catch(InterruptedException e){
//irrelevant
}
}
通常,java.util.concurrent
中的内容可以帮助您编写更强大的多线程应用程序,而不必诉诸Object#wait()
和其他并发原语(当然,除非您正在学习)。 / p>
答案 3 :(得分:0)
尝试在每个线程上设置未捕获的异常处理程序。 Thread上有一个setUncaughtExceptionHandler()函数。实现UncaughtExceptionHandler接口并打印异常。
一般的想法,但不要使用匿名类/方法:
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Throwable e)
{
e.printStackTrace();
}
});