转自:http://414149609.iteye.com/blog/1204591
一、没有任何语言方面的需求一个被中断的线程应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断。
我一直都以为调了thread.interrupt()后,线程就立刻停止(类似已被废弃的stop函数),如果真的这样,那会让尚未处理完的数据和状态处于不可知的情况,容易导致不可预计的问题。interrupt更像一个通知,将Thead里的中断标志位设为true,而线程能否退出,就看用户的代码对于这个通知是怎么处理的了。
二、对于处于sleep,join等操作的线程,如果被调用interrupt()后,会抛出InterruptedException,然后线程的中断标志位会由true重置为false,因为线程为了处理异常已经重新处于就绪状态。
我在运行thinking in java里中断的例子时,一直都很奇怪为什么在catch(InterruptedException e)的处理段里,thead.isInterrupted()返回的都是false,原来是已被重置。
三、循环任务线程的中断
1、任务类里做一个信号变量boolean isStopped。循环每次都检查信号量,如果外部逻辑将isStopped设为true,则线程退出。
2、利用线程类已有的信号量isInterrupted。由于sleep、join、wait等操作会抛出中断异常,然后中断标志会被紧接着重置,所以需要做好异常处理。有两种推荐的编码结构:
1.public void run() {
2. try {
3. ...
4. /*
5. * 不管循环里是否调用过线程阻塞的方法如sleep、join、wait,这里还是需要加上
6. * !Thread.currentThread().isInterrupted()条件,虽然抛出异常后退出了循环,显
7. * 得用阻塞的情况下是多余的,但如果调用了阻塞方法但没有阻塞时,这样会更安全、更及时。
8. */
9. while (!Thread.currentThread().isInterrupted()&& more work to do) {
10. do more work
11. }
12. } catch (InterruptedException e) {
13. //线程在wait或sleep期间被中断了
14. } finally {
15. //线程结束前做一些清理工作
16. }
17.}
1.public void run() {
2. while (!Thread.currentThread().isInterrupted()&& more work to do) {
3. try {
4. ...
5. sleep(delay);
6. } catch (InterruptedException e) {
7. Thread.currentThread().interrupt();//重新设置中断标示
8. }
9. }
10.}
四、不可中断的操作,包括进入synchronized段以及Lock.lock(),inputSteam.read()等,调用interrupt()对于这几个问题无效,因为它们都不抛出中断异常。如果拿不到资源,它们会无限期阻塞下去。
对于Lock.lock(),可以改用Lock.lockInterruptibly(),可被中断的加锁操作,它可以抛出中断异常。等同于等待时间无限长的Lock.tryLock(long time, TimeUnit unit)。
对于inputStream等资源,有些(实现了interruptibleChannel接口)可以通过close()方法将资源关闭,对应的阻塞也会被放开。