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

任務是保證順序地執行,並且不超過一個任務將是積極的,在任何給定的時間。

「處理超時」和「任務執行」之間的區別是答案的關鍵。您認爲「單線程」意味着「一次只處理一個超時」,但它的確意味着「一次只執行一個任務」。所有超時都是同時處理的,但是如果在任務停止執行之前達到一個超時,那麼它必須等待另一個完成才能執行。