繁体   English   中英

阻止和唤醒使用者线程/

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM