2012-06-22 20 views
0

同步問題:的Java HashSet的同步查詢

Set s = Collections.synchronizedSet(new HashSet()); 
private Object monitor_ = new Object(); 

//Set has element added in another routine... 

//Called by some thread1, thread2, ... 
TimerTask run(){ //method which executes every 1 min 
    synchronized(monitor_) { 
    s.isEmpty() 
    // ... 
    // waits for 30 seconds 
    // JNI call 
    // ... 
} 
} 

//Called by cleanup thread 
removecall() 
{ 
synchronized(monitor_) { 
    s.remove(something); 
} 
} 

Problem: 雖然TimerTask的run方法在執行清除線程必須等待。任何有效的方式 來處理這種情況,不得不等待。例如可重入鎖

+0

您能不能給我們'TimerTask.run()'的內容是什麼? –

+0

你的問題不是很清楚。要麼你需要timertask和cleanup線程中的2個操作是同步的,或者你不需要。如果您的目的僅僅是保證線程安全地訪問您的集合,那麼在使用synchronizedSet之前不需要額外的同步。 – assylias

+0

@assylias是希望安全訪問set,但是按照java doc http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html#synchronizedSet(java.util.Set ) 用戶在迭代時手動同步返回的集合是非常重要的。 – Sandy

回答

0

如果您使用ConcurrentLinkedQueue作爲「信使」,則可以輕鬆地在線程之間進行通信。然後,您可以簡單地將某些內容放入該隊列中,例如一個字符串,用於指示該線程是否完成工作,例如, public static String DONE = "DONE"

現在,您只需每隔一段時間輪詢一次隊列:如果它不爲空,則可以執行任何操作。這使得你的程序流程非常異步,並且很容易擴展。

0

幾件事情浮現在腦海中:

  • 當你調用monitor_.wait(),該線程釋放上monitor_鎖,synchornized上monitor_可以執行,這樣其他線程
  • 另一種選擇是,你只是等待並重寫修改哈希集的方法,以便他們調用monitor_.notify(),這將使您的run()方法脫離wait()。這將是比定期檢查更加乾淨,而且會使整個系統反應更快,因爲改變會立即代替檢測到的每一個(平均)30秒/ 2
0

試試這個,如果你想你的工作被同時完成,use 2 different objects in the synchronized block.

如:

Set s = Collections.synchronizedSet(new HashSet()); 

private Object monitor_1 = new Object(); 
private Object monitor_2 = new Object(); 

TimerTask run(){ //method which executes every 1 min 
    synchronized(monitor_1) { 
    s.isEmpty() 

} 
} 


removecall() 
{ 
synchronized(monitor_2) { 
    s.remove(pcg); 
} 

}