2014-04-04 22 views
1

我有點困惑Future.get(timeout)如何按照它在定義的超時時間後通過異常的定義工作,但是它並沒有在我的測試用例中發生。未來的get()方法如何與超時一起工作

import java.util.LinkedHashSet; 
import java.util.Set; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 
import java.util.concurrent.TimeUnit; 

public class CallableExample { 

public static class WordLengthCallable implements Callable<String> { 
    private String word; 
    private long waiting; 

    public WordLengthCallable(String word, long waiting) { 
     this.word = word; 
     this.waiting = waiting; 
    } 

    public String call() throws InterruptedException { 
     Thread.sleep(waiting); 
     return word; 
    } 
} 

public static void main(String args[]) throws Exception { 
    args = new String[] { "i", "am", "in", "love" }; 
    long[] waitArr = new long[] { 3000, 3440, 2500, 3000 }; 
    ExecutorService pool = Executors.newFixedThreadPool(3); 
    Set<Future<String>> set = new LinkedHashSet<Future<String>>(); 
    int i = 0; 
    for (String word : args) { 
     Callable<String> callable = new WordLengthCallable(word, waitArr[i++]); 
     Future<String> future = pool.submit(callable); 
     set.add(future); 
    } 
    String sum = ""; 
    for (Future<String> future : set) { 
     try { 
      sum += future.get(2000, TimeUnit.MILLISECONDS) + ", "; 
     } catch (Exception e) { 
     } 
    } 
    System.out.print("Result : " + sum); 
} 
} 

輸出 「上午,在」

它表現不同上改變陣列(timeArr值)的等待時間。何時使用獲取超時?

回答

2

在你的for-loop中,你等待第一個未來完成。這可能需要2000毫秒。此時所有其他線程都會休眠。因此,其他線程的所有值都是2000毫米。然後你等待2000毫秒,也許你等待退貨的未來。因此,兩個或更多的線程將會成功。

在循環的每次迭代中,您都會向另一個線程捐贈2000毫秒。只有當一個未來的回報成功時,你纔會對剩餘的未來捐款減少。如果你想觀察所有未來的失敗,由於2000毫秒的超時,你將不得不併行處理它們。

如果你改變一些你的代碼是這樣的:

Set<Callable<String>> tasks = new HashSet<>(); 
for (String word : args) { 
    tasks.add(new WordLengthCallable(word, waitArr[i++])); 
} 
List<Future<String>> futures = Executors.newFixedThreadPool(3) 
     .invokeAll(tasks, 2000, TimeUnit.MILLISECONDS); 

你應該看到,沒有任何的任務將獲得成功,由於等候時間:

3000, 3440, 2500, 3000 

爲每個創建Callable ,都大於2000.

+0

你是對的,謝謝你的時間:) – RQube

+0

歡迎您! – Harmlezz

+0

執行與您的描述非常相似,但爲什麼最後一個任務有3000毫秒的等待時間拋出異常,請證明。 – RQube

1

編輯︰感謝@RQube警告我關於線程的執行順序爲3.線程將完成前1.,4.線程無線我會在3.完成後開始,而不是1.

首先你的線程池的大小是3.這意味着你的4.未來將等待3.完成。

讓我們假設除了線程等待之外,沒有耗時的工作。執行將是這樣的:

  1. 未來 - 3000ms的等待時間 - 這將拋出超時異常,但繼續運行,因爲你不終止它超時。所以你的4.未來還在等待一個線程完成。 總執行時間:2000ms

  2. 未來 - 1440ms等待,因爲您已經等待2000ms - 這將返回,就像您在輸出「am」中看到的那樣。也是在2500毫秒標記3.未來將被執行,並且4.未來將在2500毫秒標記開始。 總執行時間:3440ms

  3. 未來 - 沒有等待時間,因爲我們已經等待3440ms,這將立即返回。 總執行時間:3440ms。

  4. 未來-2060ms等待時間,因爲這已經開始於2500毫秒標記和開始後940毫秒已經過去。當你調用get(),但實際上它們都將執行此將超時2000毫秒後(等待2940ms)

正如你所看到的只是2和3。期貨將返回。

對不起,格式不正確,任何錯別字,因爲我寫在手機上。

+0

感謝您的時間,幾更多的研發和@harmlezz的幫助我瞭解情況。它與您的描述完全相同,但第四項任務將在具有最少等待時間的頭三項任務之一完成時開始。由於第三項任務的最短等待時間爲2500毫秒,因此第四項任務將在2500毫秒後開始,而不是3000毫秒。 – RQube

+0

是的,我錯過了,謝謝你的迴應:) –

相關問題