2013-06-24 76 views
1

我看過問題How do determine if an object is locked (synchronized) so not to block in Java?
但我有問題,我找不出解決方案。
在我的Web應用程序中,刷新數據容器的過程可能需要很長時間。刷新被迫按時間間隔進行。當然,當一個刷新仍然在容器上工作時,另一個不能(不會破壞容器中的數據)。
我想用後臺線程刷新容器。多個後臺工作人員可以同時在多個容器上工作(不同用戶會話的不同工作人員,每個用戶會話的容器中可以有不同的數據)。
當然,我可以在工作人員處做synchronize(myContainer)以強制任何其他工作人員當前未更新此特定容器。但我寧願要檢查是否有任何工人在集裝箱上工作並退出,如果是。另外我想不更改容器的代碼,所以我不想在容器類中添加ReentrantLock並鎖定它。
因此,工作人員有MyContainer實例,並且想要確定是否有其他worker正在刷新此容器實例。如何在不鎖定的情況下同步對象?

任何想法如何實現?

回答

2

使用AtomicBoolean,把這段代碼在你的MyContainer類:

AtomicBoolean isRefreshing = new AtomicBoolean(false); 

void refresh() { 
    if (isRefreshing.compareAndSet(false, true)) { 
    try { 
     // refresh 
    } finally { 
     isRefreshing.set(false); 
    } 
    } 
} 

如果你不能碰myContainer中,也許創造RefreshWrapper持有的AtomicBoolean和myContainer中的實例。

1

我會把容器中,ConcurrentLinkedQueue,並有工作線程poll隊列即

Container container; 
while((container = queue.poll()) != null) { 
    container.refresh(); 
} 

然後,你必須根據它們被刷新的容器是否正在跟蹤兩個選項。

  • 如果他們是那麼你可以offer刷新的容器一刷新就重新回到隊列中。您可以使用if(container.refreshTime < X)後衛來確保您不會在相同的時間間隔內刷新容器兩次。
  • 如果他們沒有,那麼你既可以
    • 使用兩ConcurrentLinkedQueues和它們之間的交替:在queue1offerqueue2刷新容器,pollqueue1是空的休眠狀態,直到下一個時間間隔,在這一點pollqueue2offer更新容器上queue1
    • 或者,在工作線程完成刷新所有容器並已進入睡眠狀態時,將容器的數組保存在主線程中,並將容器保留回隊列中。
+1

'ConcurrentLinkedQueue'是非阻塞的,這意味着如果OP不小心,while循環可以做一些嚴重的忙碌轉動 –

+0

@John Vint我假設隊列已經擁有所有的容器,工作線程將啓動,如果容器立即重新添加到隊列中或者立即添加到與原始隊列交替的另一個隊列中,情況就會如此。如果不是這種情況,那麼'BlockingQueue'會是更好的選擇 - 如果容器被同時添加到隊列中並從隊列中移除,我的回答中的循環不會忙碌,但它會冒着過早終止的風險。 –

+0

@JohnVint:實際上,我的答案也有同樣的缺點,但我認爲限制刷新的頻率超出了這個問題的範圍,OP應該有適當的方法來解決這個問題。否則,一個'ScheduledExecutorService'將是很好的解決方案。 –

0

如果您需要預先檢查對象尚未被其他線程鎖定,這應該是可能的Thread.holdsLock方法。如果這還不夠,請查看advanced lock classes。這些鎖提供了豐富的功能(檢查是否在鎖上等待,嘗試鎖定超時,中斷鎖定等)。他們應該提供足夠的功能來解決您的問題。

相關問題