2015-03-31 59 views
1

這裏是打擾我乞討標準補救併發問題避免可能的併發性問題與列表返回

  1. 創建一個列表對象(LST)
  2. 啓動multple線程的順序(更新主題)
  3. 將該lst發送給每個更新程序線程以更新(添加)它。
  4. 等待一段定義的時間(t1)讓更新程序線程繼續更新。
  5. t1時間到期後,將lst返回給另一個不在我們控制範圍內的應用程序(Consumer-App)。
  6. 當返回它時,更新程序線程可能仍在更新lst。
  7. Consumer-App不知道列表是否仍在由更新程序線程在後臺更新。
  8. Consumer-App在列表上執行列表操作(添加/刪除)。

問題:這會導致併發問題。

如何解決這個問題?

如何在t1之後停止更新線程有效?或者有沒有什麼標準的方法來解決這個問題? synchronizedList (Collections.synchronizedList(new ArrayList()))會幫助嗎?

編輯: 我也知道CopyOnWriteArrayList。但我關注的是簡單的ArrayList

+0

這遠遠不夠。首先,你應該考慮如何在* t1之前管理併發訪問*。如果你有解決這個問題的辦法,另一個會自然而然地出現。 – Holger 2015-03-31 18:01:19

+0

那麼,你是說我返回後,我不需要擔心,如果我更新它線程安全的方式(例如:作爲一個同步的方式?)。但我懷疑它。因爲API說:「迭代時用戶需要在返回列表上手動同步:」[ref:http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html #synchronizedList(java.util.List)] – namalfernandolk 2015-03-31 18:05:39

+0

忘掉'synchronizedList'。如上所述,這是不夠的。您需要手動訪問控制。而且一旦你實現了某種手動控制,就很容易添加一個「我們超越t1」的條件,它會拒絕從updater線程訪問列表。解釋如何做到這一點太廣泛。通過閱讀API文檔,您無法學習併發編程;你首先需要了解基本原理。我推薦閱讀Brian Goetz,Joshua Bloch,Doug Lea等人撰寫的「Java Concurrency in Practice」。 – Holger 2015-03-31 18:15:59

回答

1

您可以使用executor服務創建和終止線程,以及處理併發的CopyOnWriteArrayList。

private CopyOnWriteArrayList<someObject> someArrayList = new CopyOnWriteArrayList<someObject>(); 

...

class NodeStatusThread implements Runnable { 

     private ExecutorService UpdaterThreadExecutor = null; 
     private int numThrd = 20; //threads 
     private int timeout = 10; // ten-seconds 

     @Override 
     public void run() { 
      for (int i=0;i<numThrd; i++) { 
       UpdaterThreadExecutor.execute(new UpdaterThread()); 
      } 
      UpdaterThreadExecutor.shutdown(); 


      try{ 
       //Wait for thread completion 
       if(!UpdaterThreadExecutor.awaitTermination(timeout, TimeUnit.SECONDS)){ //return false is timeout is surpassed 
        UpdaterThreadExecutor.shutdownNow(); //forces thread termination 
       } 
      }catch(InterruptedException e){ 
       UpdaterThreadExecutor.shutdownNow(); 
      } 

     } 

} 

...

class UpdaterThread implements Runnable { 

    @Override 
    public void run() { 
     omeArrayList.add(someObject); 

     someArrayList.remove(someObject); 
    } 
} 
0

4 - 等待一段規定的時間(T1),以便讓更新線程的更新進行。

這是你的設計錯誤的地方。您永遠無法確定每個線程都已完成更新列表。

您應該使用同步機制,讓消費者線程等待,直到每個生產者完成。使用CountDownLatchCyclicBarrier

+0

謝謝你的建議史密斯先生。但我想指出,我提到「繼續進行更新」而不是「完成更新」。我知道不確定線程​​是否完成。如果我假設它已經完成,那麼我不擔心Consumer-App在它上面列出操作時發生的併發問題(請檢查後面的點也像第6個那樣)。 – namalfernandolk 2015-04-01 17:50:53