我有这个问题,我有
private ScheduledExecutorService executor =
Executors.newSingleThreadScheduledExecutor();
和每50毫秒创建的任务:
executor.scheduleAtFixedRate(myTask, 0, 50, TimeUnit.MILLISECONDS);
myTask
有时需要一段时间才能完成(比如2-3秒左右),但是newSingleThreadScheduledExecutor会保证下一个预定的myTask会等到当前的myTask完成。
但是,我不时会收到此错误:
执行:java.util.concurrent.RejectedExecutionException
我该怎么办?感谢
答案 0 :(得分:13)
考虑执行者正在做什么。根据您的说明,它每50毫秒运行一个任务。假设这个任务运行时间不到50毫秒,那么一切都很好。但是,每隔一段时间运行需要2-3秒。发生这种情况时,执行程序仍然会尝试每50毫秒执行一次,但因为它只有一个线程,所以它不能,并且拒绝那些在长时间运行的任务仍在进行时被触发的执行。这会导致你看到的异常。
你有两个选择来解决这个问题(假设你想坚持使用一个线程):
使用scheduleWithFixedDelay
而不是scheduleAtFixedRate
。如果你仔细阅读javadoc,你会发现scheduleWithFixedDelay
将在完成一个任务和下一个任务的开始之间等待50毫秒,所以它永远不会“重叠”,即使其中一个需要很长时间时间。相反,scheduleAtFixedRate
将尝试每50毫秒执行一次,无论每个花费多长时间。
更改执行程序处理执行失败的方式。默认情况下是记录异常,但您可以告诉它忽略它,例如。看一下java.util.concurrent.RejectedExecutionHandler
的子类,例如DiscardPolicy
,它只是默默地删除了无法运行的任务。您可以通过直接构造ScheduledThreadPoolExecutor
并将处理程序传递给构造函数来使用它们,而不是使用Executors
工厂类。
我怀疑选项(1)就是你想要的。
答案 1 :(得分:4)
以下任何一种情况都会抛出此异常:
我认为后者正在发生。执行任务时需要很长时间,因此无法运行后续计划任务,因为池中没有足够的可用线程。
或者:
答案 2 :(得分:-1)