[英]Blocking and simultaneously releasing a variable number of threads in Java
我正在Java中建立一個緩沖區,該緩沖區將收集許多線程請求的寫操作,並將它們作為一組刷新,例如每秒刷新一次。 我想給它一個名為waitForFlush
的方法,該方法將阻止和線程調用它,直到下一個刷新事件完成為止。 同時,一個單獨的獨立線程正在刷新並在循環中休眠。 因此,我基本上是在尋找一種並發結構或模式,該結構或模式將允許許多線程在特定點處阻塞,然后同時釋放它們,並且我發現Java的內置並發原語與之完全不匹配。 。 到目前為止,我想出的最好的方法是wait / notifyAll,如下所示:
public class Buffer {
private volatile long lastFlushTime = System.currentTimeMillis();
private final Object flushMonitor = new Object();
public void waitForFlush() {
long entryTime = System.currentTimeMillis();
synchronized(flushMonitor) {
while(lastFlushTime <= entryTime) {
flushMonitor.wait();
}
}
}
public void flush() {
// do flush stuff here
synchronized(flushMonitor) {
lastFlushTime = System.currentTimeMillis();
flushMonitor.notifyAll();
}
}
}
盡管我認為這在實踐中會很好,但是waitForNotify()
的同步塊對我來說仍然有些不完善。 理想情況下,對於此用例,您可以在不同步關聯的Object的情況下調用wait()
,並且所有被阻塞的線程都將在調用notifyAll()
同一時刻釋放,而不必退出同步塊一對一。
因此,總的來說,有沒有比我上面概述的更好的方法來阻塞並同時釋放可變數量的線程(我認為Semaphore和CountDownLatch類僅適用於固定數量的線程)?
正如Marko Topolnik和munyengm所提到的,盡管CountDownLatch可以在一個時間范圍內使用。 它在循環情況下會失敗(也就是說,每個CDL您只能await
一次& countDown
)。 然后,您可以考慮使用CyclicBarrier,但這在您的情況下會失敗,因為您需要知道所使用的線程數。
如果可以使用Java 7,建議使用Phaser 。 您可以將單線程信號發送給許多等待線程並重用。
final Phaser phaser = new Phaser(1);//register one thread to arrive
public void waitForFlush() {
int phase = phaser.getPhase();
phaser.awaitAdvance(phase);
}
public void flush() {
lastFlushTime = System.currentTimeMillis();
phaser.arrive(); //signals all waiting threads on the current phase and will increment the phase by 1
}
如果您正確使用CountDownLatch
,我認為它可以為您完成此任務。 辦法是使可變數量的線程在閂鎖上await
,然后刷新線程調用countDown
。 閂鎖始終初始化為1。這是它的工作方式:
public class FlushControl
{
private volatile CountDownLatch latch = new CountDownLatch(1);
public void awaitFlush() throws InterruptedException { latch.await(); }
public void flush() {
final CountDownLatch l = latch;
latch = new CountDownLatch(1);
l.countDown();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.