关于使用interrupt代替volatile进行中断的例子的看法
来源:5-12 停止失效

KimZing
2019-09-09
一、While判断条件
例子中在while判断中使用Thread.currentThread().isInterrupted()
替换!canceled
,一开始对这一块有误解,以为是因为加了Thread.currentThread().isInterrupted()
程序才会正常响应中断。
- 不加这一个判断,也是完全可以正常中断的,真正中断的地方是put()阻塞方法对interrupt()进行了响应,抛出了InterruptedException, 进入catch块,打印了日志,并最终执行finnaly块代码。
- 多加
Thread.currentThread().isInterrupted()
只是多了一个检查的点。 - 某种角度来说,如果wait()/sleep()…支持自定义的中断信号,可以响应
canceled
的话,也是没啥问题的。
二、关于try的作用范围
从代码编写的角度,try作用范围扩大到while外层,对性能有一定帮助,但觉得这个例子在内部捕捉异常,使用break跳出循环,或许更易于理解。
自己写了个low的例子,说明自己的理解,谢谢老师的讲解
public class VolatileStopThreadReplaseWithInterrupt {
public static void main(String[] args) throws InterruptedException {
// 容纳10个元素的阻塞队列
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
Producer producer = new Producer(queue);
Thread thread = new Thread(producer);
// 启动生产者
thread.start();
// 直接用主线程当消费者
while (Math.random() < 0.9D) {
System.out.println("消费:" + queue.take());
// 消费很慢,导致生产者会被阻塞
Thread.sleep(100);
}
System.out.println("消费线程停止消费,并通知生产者停止生产");
thread.interrupt();
}
}
class Producer implements Runnable{
private BlockingQueue<Integer> blockingQueue;
public Producer(BlockingQueue<Integer> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
try {
System.out.println("生产:" + i);
// 阻塞方法
blockingQueue.put(i);
} catch (InterruptedException e) {
System.out.println("生产线程接收到中断信号");
break;
} finally {
System.out.println("生产线程已经停止生产元素");
}
}
}
}
1回答
-
不加这一个判断,也是完全可以正常中断的,真正中断的地方是put()阻塞方法对interrupt()进行了响应,抛出了InterruptedException, 进入catch块,打印了日志,并最终执行finnaly块代码。
多加Thread.currentThread().isInterrupted()只是多了一个检查的点。
对的,虽然这个例子中,是put对interrupt进行了响应,但是不一定每个业务逻辑都会用到put,所以通常情况下,加上Thread.currentThread().isInterrupted()这个判断点可以更稳妥。
某种角度来说,如果wait()/sleep()…支持自定义的中断信号,可以响应canceled的话,也是没啥问题的。
对的,如果可以支持自定义信号,那就没问题。
从代码编写的角度,try作用范围扩大到while外层,对性能有一定帮助,但觉得这个例子在内部捕捉异常,使用break跳出循环,或许更易于理解。
自己写了个low的例子,说明自己的理解,谢谢老师的讲解
不客气,我觉得这两种try范围都可以,只要能表达“遇到中断就退出”的含义就可以。
312019-09-10
相似问题