在 ArrayBlockingQueue
,在 put
方法中,为什么在捕获 InterruptedException
后调用 notFull.signal()
?当线程要终止时,为什么会发出“未满”信号?
来自source :
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
final E[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
try {
while (count == items.length)
notFull.await();
} catch (InterruptedException ie) {
notFull.signal(); // propagate to non-interrupted thread
throw ie;
}
insert(e);
} finally {
lock.unlock();
}
}
最佳答案
想象一下以下场景:
- 线程 1 和 4 正在等待
notFull
,即,队列已满,锁被释放。 - 线程 2 持有锁,并且即将从队列中删除一个元素。
- 线程 3 中断线程 1。
现在想象一下以下交错:
+-+--+--------+-----------+------- TIME +---+------------+---------------------->
| | | | | | | |
+---------+ +------------------+ +----------+ |
| Thread2 | | Thread2 | | Thread2 | |
| lock() | | notFull.signal() | | unlock() | |
+---------+ +------------------+ +----------+ |
| | | | |
+---------------------+ | | |
| Thread3 | | | |
| Thread1.interrupt() | | | |
+---------------------+ | | |
| | | |
+---------------+ +-------------+ +---------+ +----------------------+
| Thread1 | | Thread1 | | Thread1 | | Thread1 |
| interrupted() | | signalled() | | lock() | | InterruptedException |
+---------------+ +-------------+ +---------+ +----------------------+
如果 InterruptedException
没有被捕获,并且线程 1 只是解锁并放弃等待怎么办?仍在等待 notFull
信号的线程 4 会发生什么情况?信号已经被线程 2 发送,但恰好接收线程线程 1 被中断,信号被浪费了。
简而言之:如果线程在被中断时收到信号,它将将该信号传递给另一个线程,这样信号就不会丢失。这可以防止线程无限期地等待已经发生的事情。
关于java - 为什么 ArrayBlockingQueue 在捕获 InterruptedException 后会发出 'not full' 信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21691638/