阻塞操作不可取消
程序员文章站
2022-04-24 14:25:06
...
public class BlockedInterrupteTest extends Thread{
private final BlockingQueue<BigInteger> queue;
private volatile boolean cancelled = false;
BlockedInterrupteTest(BlockingQueue<BigInteger> queue){
this.queue = queue;
}
public void run() {
try {
BigInteger p = BigInteger.ONE;
while(!cancelled){
queue.put(p = p.nextProbablePrime());
}
}catch (InterruptedException e){}
}
public void cancel() {
cancelled = true;
}
}
BlockingQueue是阻塞队列,它的put操作会在队列满时一直阻塞。
/**
* Inserts the specified element into this queue, waiting if necessary
* for space to become available.
*
* @param e the element to add
* @throws InterruptedException if interrupted while waiting
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this queue
*/
void put(E e) throws InterruptedException;
所以,当其他线程调cancel()函数时,如果当前线程执行queue.put(p = p.nextProbablePrime()); 阻塞了,是无法停止当前线程的。
解决办法是使用线程中断来替代自定义的取消标识:
public void run() {
try {
BigInteger p = BigInteger.ONE;
while(!Thread.currentThread().isInterrupted()){
queue.put(p = p.nextProbablePrime());
}
}catch (InterruptedException e){}
}
public void cancel() {
interrupt();
}
即使put是阻塞的,也会响应线程中断,从而达到取消操作的目的。