2013-04-11 158 views
1

我有一個簡單的工具,它坪一組節點,並返回一個字符串到未來的對象一個ArrayList將被輸出到文件中。程序應該運行直到用戶終止。Java線程:期貨只用結果從第一和最後一個線程

它不會出現未來接收結果(或至少將它們傳遞給該方法,以輸出到文件)。不管我同時運行的線程數量(總是小於100,由輸入文件決定),我只輸出第一個和最後一個初始化線程的結果。

作爲一個全面的檢查,我創建了一個全局變量,其中每個線程將關閉並返回其結果對未來對象之前發送其結果。這個變量被所有線程正確更新。

沒有人有任何想法,爲什麼未來似乎沒有被接收我從線程所有結果?

public class PingUtility{ 
    public static ExecutorService pool = Executors.newFixedThreadPool(100); 
    static Future<ArrayList<String>> future; 

    public static void main(String[] args) throws Exception { 

     Timer timer = new Timer(); 
     TimerTask task = new TimerTask(){ 
      public void run(){ 
       //Creates a pool of threads to be executed 
       ArrayList<String[]> nodes = new ArrayList<String[]>() 
       future = pool.submit(new PingNode(nodes)); 
       } 
      } 
     }; 

     timer.scheduleAtFixedRate(task, 0, interval); 

     while(true){ 
      try{ 
       ArrayList<String[]> tempOutputArray = future.get(); 
       Iterator<String[]> it = tempOutputArray.iterator(); 
       while(it.hasNext()) appendFile(it.next()); 
       tempOutputArray.clear(); 
      }catch(Exception nullException){ 
      //Do nothing 
      } 
     } 
    } 
+0

只是爲了後人,你應該總是記錄異常(特別是NPE)。如果迭代器可以得到一個'null',那麼你應該在代碼中處理它。 – Gray 2013-04-11 14:33:24

回答

3

你的問題是,你正在修改的future靜態字段,而無需在定時任務線程(S)同步,並在主線程讀取它。您需要在修改時對其進行同步,或者使用其他機制在線程之間共享信息。

我建議從static字段切換到LinkedBlockingQueue作爲一種更好的方式發送信息從PingNode調用appendFile(...)方法。這節省了從需要自己做同步,並防止在比賽條件,其中多個定時器任務將開始,消費者可以從get()他們之前覆蓋future。可能是這樣的:

BlockingQueue<String[]> queue = new LinkedBlockingQueue<String[]>(); 
... 

// inside of run, producer passes the queue into the PingNode 
public void run() { 
    pool.submit(new PingNode(queue)); 
} 

// consumer 
while (true) { 
    String[] array = queue.take(); 
    ... 
} 

這不會影響您完成後如何停止線程。如果定時器任務被終止,實體可以向隊列添加一個終止對象來停止主循環。

+0

謝謝,我將不得不考慮如何正確實施它。 – Yabo9797 2013-04-11 14:08:19

+0

我的意思是排隊字符串[]。那麼在你的例子中,我根本不會使用未來?隊列被用於存儲PingNode的結果嗎?如果是這樣,我想我需要修改方法來同時處理輸入和隊列來處理輸出? – Yabo9797 2013-04-11 14:23:08

+0

是的,不需要使用'未來'。我考慮推薦一個'BlockingQueue ',但似乎沒有必要。你將一個'List'傳遞給'PingNode',所以直接傳入'queue'是有道理的。 – Gray 2013-04-11 14:30:09

0

Future對象是不是一個倉,像一個ArrayList,它僅僅指向一個單一的計算結果。因爲你只有一個指向這個Future的靜態指針,我想象的是這樣的:

future = null 
    nullException 
    nullException 
    nullException 
    nullException 
    ... 
    First thread finally sets future = Future<ArrayList<String>> 
    Call to future.get() blocks... 
     Meanwhile, all other threads get scheduled, and they reassign future 
     The last thread will obviously get the last say in what future points to 
    Data is gathered, written to file, loop continues 
    future now points to the Future from the last thread 
    Results from last thread get printed 
+0

謝謝,這聽起來像是怎麼回事。你會推薦LinkedBlockingQueue嗎?有沒有辦法通過將它們放入類似對象的容器中來處理結果,我只需要抓住第一個結果,然後處理它,然後轉到下一個結果? – Yabo9797 2013-04-11 14:07:59

+0

這就是LinkedBlockingQueue的功能。線程put()到隊列阻塞,直到另一個線程poll()從它那裏獲得,同樣,poll()的線程將掛起,直到另一個線程放入()爲止。 – torquestomp 2013-04-11 14:22:26

相關問題