我正在使用一个java.util.concurrent.ExecutorService
我通过调用获得的Executors.newSingleThreadExecutor()
. This ExecutorService
有时会停止处理任务,即使它尚未关闭并继续接受新任务而不抛出异常。最终,它建立了足够的队列,我的应用程序将关闭OutOfMemoryError
例外情况。
文档似乎表明,如果有必要,这个单线程执行器应该通过启动一个新的工作线程来替换已经死亡的线程,从而避免任务处理错误。我错过了什么吗?
听起来您有两个不同的问题:
1)你的工作队列过多。你不能只是不断地将新任务塞进队列,而不考虑任务执行器的消耗率。您需要找出一些逻辑来了解何时阻止向工作队列添加新内容。
2)任务线程中任何未捕获的异常都可以完全杀死该线程。当这种情况发生时,ExecutorService 会启动一个新线程来替换它。但这并不意味着您可以忽略导致线程终止的任何问题!找到那些未捕获的异常并捕获它们!
这只是一种预感(因为您的帖子中没有足够的信息来了解其他情况),但我不认为您的问题是任务执行器停止处理任务。我的猜测是,它处理任务的速度不如您创建任务的速度。 (事实上,你的任务有时会过早终止,这可能与问题是正交的。)
至少,这是我使用线程池和任务执行器的经验。
好吧,根据您的评论,这是另一种听起来可行的可能性(一切都会顺利运行几个小时,直到突然停止)......
您的任务线程之间可能会出现罕见的死锁。大多数时候,你很幸运,僵局不会自行显现。但有时,两个或多个任务线程会进入等待释放另一个线程持有的锁的状态。此时,无法进行更多任务处理,并且您的工作队列将堆积起来,直到出现 OutOfMemoryError 错误。
以下是我诊断该问题的方法:
消除任务线程之间的所有共享状态。首先,这可能需要每个任务线程为其所需的所有共享数据结构制作防御性副本。一旦你这样做了,就完全不可能遇到僵局了。
此时,逐渐重新引入共享数据结构,一次一个(具有适当的同步)。每次微小修改后重新运行应用程序以测试死锁。当您再次遇到崩溃情况时,请仔细查看共享资源的访问模式并确定是否确实需要共享它。
对我来说,每当我编写使用线程池和执行器处理并行任务的代码时,我总是尝试消除ALL这些任务之间共享状态。就应用程序而言,它们也可能是完全自主的应用程序。寻找死锁是一件很麻烦的事情,根据我的经验,消除死锁的最佳方法是让每个线程拥有自己的本地状态,而不是与其他任务线程共享任何状态。
祝你好运!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)