5

我是新来ExecutorService,不知为什么下面的代码正确打印“10 15”,尽管我只创建一个线程来处理超时?为什么我可以多次调用时间表而无需在单个线程执行器上取消先前的任务?ScheduledExecutorService的一个线程很多任务

import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 


public class TestExecutorService implements Runnable { 
    public static ScheduledExecutorService SERVICE = Executors.newSingleThreadScheduledExecutor(); 
    private int delay; 


    public TestExecutorService(int delay) { 
     this.delay = delay; 
    } 

    public void run() { 
     System.out.println(delay); 
    } 

    public static void main (String[] args) { 
     SERVICE.schedule(new TestExecutorService(10), 10, TimeUnit.SECONDS); 
     SERVICE.schedule(new TestExecutorService(15), 15, TimeUnit.SECONDS); 

     SERVICE.shutdown(); 
    } 
} 
+0

额外阅读http://code.nomad-labs.com/2011/12/09/mother-fk-the-scheduledexecutorservice/ – cherit

回答

8

在这种情况下阅读Javadoc会很有帮助。它解释说,虽然执行将一个线程被创建,它将与无界队列方式来运行。这意味着您可以向执行程序提交多个任务,并且它们将排队等待一个接一个地运行,直到队列的最大范围(在本例中为无穷大)或直到JVM耗尽资源。

创建一个执行器,该执行器使用单个工作线程运行在无界队列中的一个 。 (但是请注意,如果单个线程关闭前的执行期间终止 由于故障,一个新的人会 如果需要执行后续任务,取代它的位置。)的任务是 保证顺序地执行,并且不超过一个任务在任何给定时间将为 有效。与其他等效 的newFixedThreadPool(1)返回的执行程序保证不会是 可重构使用其他的线程。

在你的例子中,你的两个任务被排队,然后依次运行,这就是你得到(预期)输出的原因。

+1

因此,如果提交了许多延迟相同的任务,那么其中一些任务会稍后打印? –

+1

@尼古拉·库兹涅佐夫是的,他们会假设任务需要足够长时间才能注意到。 – Brian

7

Javadocs

任务是保证顺序地执行,并且不超过一个任务将是积极的,在任何给定的时间。

“处理超时”和“任务执行”之间的区别是答案的关键。您认为“单线程”意味着“一次只处理一个超时”,但它的确意味着“一次只执行一个任务”。所有超时都是同时处理的,但是如果在任务停止执行之前达到一个超时,那么它必须等待另一个完成才能执行。