[英]block and wakeup consumer threads/
我有2个线程。
它们每个都从共享缓冲区读取一些数据。
currentDataBuffer.get(thisID); //currentDataBuffer is my shared buffer object
我想在每次调用get之后都阻塞每个线程,并在所有线程读取缓冲区(一次)时将其释放,因此我使用了currentDataBuffer
对象作为锁:
currentDataBuffer.get(thisID);
synchronized (currentDataBuffer ) {
currentDataBuffer.wait();
}
问题是当所有线程完成从缓冲区的读取(每个一行)时,如何释放那些线程?
在currentDataBuffer
内部,我有一个映射,其中存储了从缓冲区读取数据的线程的ID。
我如何使用this.notifyAll();
(从currentDataBuffer
)唤醒所有锁定的线程?
我建议您使用Java BlockingQueue数据结构。 调用BlockingQueue.take()
阻塞直到元素可用。 所以代替:
currentDataBuffer.get(thisID);
synchronized (currentDataBuffer ) {
currentDataBuffer.wait();
}
您将拥有:
currentDataBuffer.take();
可以通过调用BlockingQueue.offer(object)
方法将元素添加到队列中来释放在take()
调用中阻塞的线程。
继续执行您的代码的答案可能是使用currentDataBuffer.notifyAll()
而不是this.notifyAll()
(目前尚不清楚this
指的是什么)。 但是,您如何确保在所有线程都已读取缓冲区并进入等待状态之后notifyAll
进行调用?
如果您知道应该读取缓冲区的线程数,则更好的解决方案是使用两个CountDownLatch 。 该类的javadoc中有一个很好的例子。
------------更新:
您无需更改阅读器线程的代码。 您应该将闩锁保存在currentDataBuffer
对象中。 在currentDataBuffer
中创建一个线程,等待n
项锁存器。 在get
方法中,读取完成后,在该闩锁上调用CountDownLatch.countDown()
。 哦,我会写:
class CurrentDataBuffer implements Runnable {
private CountDownLatch singleThreadFinishedSignal;
private CountDownLatch allThreadsFinishedSignal;
public CurrentDataBuffer(int N) {
singleThreadFinishedSignal = new CountDownLatch(N); // waiter thread waits on this
allThreadsFinishedSignal = new CountDownLatch(1); // reader threads wait on this after finished reading
}
public void run() {
try {
singleThreadFinishedSignal.await(); // wait for all reader threads to finish
allThreadsFinishedSignal.countDown(); // let all reader threads proceed
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void get() {
try {
// read buffer item here ///////////////////
singleThreadFinishedSignal.countDown(); // mark that a thread has read the item
allThreadsFinishedSignal.await(); // wait for other reader threads to finish
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我认为CountdownLatch( http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html )会有所帮助。
即用初始值为2的CountDownLatch扩展您的currentDataBuffer(或要处理的线程数)。 处理完线程后,先调用latch.countDown(),然后再调用latch.await()。
为了安全起见,您可能要小心countDowns不会丢失(例如,如果引发异常)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.