Java:SingleThreadScheduledExecutor&java.util.concurrent.RejectedExecutionException

And*_*rey 8 java concurrency multithreading exception executor

我有这个问题,我有

private ScheduledExecutorService executor =  
     Executors.newSingleThreadScheduledExecutor(); 
Run Code Online (Sandbox Code Playgroud)

和每50毫秒创建的任务:

executor.scheduleAtFixedRate(myTask, 0, 50, TimeUnit.MILLISECONDS);
Run Code Online (Sandbox Code Playgroud)

myTask 有时需要一段时间才能完成(比如2-3秒左右),但newSingleThreadScheduledExecutor保证下一个预定的myTask将等到当前的myTask完成.

但是,我不时会收到此错误:

执行: java.util.concurrent.RejectedExecutionException

我该怎么办?谢谢

ska*_*man 13

考虑执行者正在做什么.根据您的说明,它每50毫秒运行一个任务.假设这个任务运行时间不到50毫秒,那么一切都很好.但是,每隔一段时间运行需要2-3秒.当发生这种情况时,执行仍试图执行每50毫秒,但因为它只有一个线程,它不能,并拒绝正在而你的长时间运行的任务仍然会触发这些处决.这会导致您看到的异常.

你有两个选择来解决这个问题(假设你想坚持使用一个线程):

  1. 使用scheduleWithFixedDelay而不是scheduleAtFixedRate.如果你仔细阅读Javadoc中,你会看到,scheduleWithFixedDelay会等待一个任务的结束和下一个开始之间50毫秒,所以它永远不会"重叠",即使其中一人需要很长的时间.相反,scheduleAtFixedRate无论每个花费多长时间,都会尝试每50毫秒执行一次.

  2. 更改执行程序处理执行失败的方式.默认情况下是记录异常,但您可以告诉它忽略它,例如.java.util.concurrent.RejectedExecutionHandler例如DiscardPolicy,看看它的子类,它只是默默地删除了无法运行的任务.您可以通过直接构造ScheduledThreadPoolExecutor并将处理程序传递给构造函数来使用它们,而不是使用Executors工厂类.

我怀疑选项(1)是你想要的.

  • @skaffman:实际上它正好与你在1.中所说的完全相反.:) javadoc:scheduleAtFixedRate:如果此任务的任何执行时间超过其周期,则后续执行可能会延迟,但不会同时执行 (3认同)