2012-06-04 74 views
4

我想調用一個HashSet的add函數有一些延遲,但沒有阻塞當前線程。有沒有簡單的解決方案來實現這樣的事情:如何使延遲非阻塞函數調用

Utils.sleep(1000, myHashSet.add(foo)); //added after 1 second 
//code here runs immediately without delay 
... 
+1

您的問題的直接答案如下。但是,試圖做什麼似乎相當不自然,這表明也許你應該尋找一個完全不同的解決方案。你想提供一些更多的上下文,爲什麼你想延遲添加? – Jochen

+0

我正在使用[Storm](https://github.com/nathanmarz/storm)來實現爬蟲。抓取的URL由包含線程ID和板號的模式生成。抓取工具的性質使得每個電路板只能處理一個URL。我的HashSet包含當前可以抓取的所有主板的ID。對單個網址的抓取可能因爲不同的原因而失敗(線程被刪除,404,...)。有些原因允許重試抓取。關於這些原因的信息被保存在不鎖定的DB中,所以在決定是否重試之前應該有一些延遲。 – Thomas

+0

這聽起來不必要的複雜。爲什麼爬網線程無法處理返回值,並且在發生可恢復故障時直接重試,或者至少將URL添加回地圖(隊列可能更適合此操作)。 – Jochen

回答

3

您可以使用ScheduledThreadPoolExecutor.schedule

ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1); 

exec.schedule(new Runnable() { 
      public void run() { 
       myHashSet.add(foo); 
      } 
    }, 1, TimeUnit.SECONDS); 

它將在一個單獨的線程在1秒鐘後執行代碼。儘管如此,請注意myHashSet的併發修改。如果您從另一個線程同時修改集合或嘗試迭代它,則可能會遇到問題,並且需要使用鎖。

9

的單純功能的解決辦法是:

new Thread(new Runnable() { 
     public void run() { 
      try { Thread.sleep(1000); } 
      catch (InterruptedException ie) {} 
      myHashSet.add(foo); 
     } 
    }).start(); 

有少了很多比的ThreadPoolExecutor怎麼回事幕後。 TPE可以方便地控制線程的數量,但是如果您正在分離大量睡眠或等待的線程,那麼限制其數量可能會損害性能,而不僅僅是幫助。

如果您尚未處理此問題,並且您想同步myHashSet。請記住,你必須同步無處不在爲此做任何好事。還有其他的方法來處理這個問題,比如Collections.synchronizedMap或者ConcurrentHashMap。