线程中断Interrupt,分析线程中断,如何安全的中断线程?

线程中的中断标志位

一.与线程中断有关的3个方法:

interrupt():中断线程,改变其线程的中断标志位(仅仅只有一个通知的作用),但是否中断由自己线程判断决定。false——>true

isInterrupted():返回线程目前的中断标志位值

Thread.interrupted():返回线程目标的中断标志位,并将标志位复位 true——>false

Thread.interrupted()源码:

ClearInterrupted参数:true-中断标志位复位   false-不复位

二.线程中使用sleep,wait,join等方式会使线程阻塞,interrupt阻塞中的线程会抛出interruptedException异常,并将中断标志位复位

(true——>false)。

安全的中断线程:自定义标志+中断标志位监测

private static class TestThread  extends  Thread {
		private volatile boolean on =true;
		private long i = 0;
		
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(on &&  !Thread.currentThread().isInterrupted()){//未中断
				try {
					System.out.println("i="+i++);
					//wait,sleep,join等阻塞
					Thread.sleep(1000);
				} catch (InterruptedException e) {//T——>F
					// TODO Auto-generated catch block
					//e.printStackTrace();
					System.out.println("线程:"+Thread.currentThread().getName()+",异常中重新置位中断标志");
					Thread.currentThread().interrupt();//F——>T
					System.out.println("1-1:"+Thread.currentThread().isInterrupted());
				}
			}
			System.out.println("1-2:on:"+on+"|中断标志位:"+Thread.currentThread().isInterrupted()+"|线程名称:"+Thread.currentThread().getName());
			System.out.println("阻塞解除!");
		}
		
		public void cancel(){
			on=false;
			interrupt();//F ——>T
			System.out.println("解除cancel中,thread.getName():"+getName());//运行的线程
			//Thread.currentThread().interrupt();//中断的是主线程(即调用cancel方法的线程本身)
			System.out.println("解除cancel中,Thread.currentThread:"+Thread.currentThread().getName());//调用cancel的线程(在此是main)
		}
	}

测试main类:

public static void main(String[] args)  {
		TestThread th=new TestThread(); 
		th.start();
		Thread.sleep(5000);
		th.cancel();
	}

疑问1:为什么要自定义标志+中断标志去判断?

如果只使用flag是不安全的取消操作,阻塞后,线程不会时刻去判断while中的条件,需要等待被唤醒(而interrupt后线程会立即响应)才会去检查条件是否满足。
中断的操作首先改变flag,再使用interrupt() 
1.如果只使用flag去判断,出现interrupt()异常,未成功把中断标志置为true,也不能代表中断已经成功。
2.如果只使用!Thread.currentThread().isInterrupted(),假如在程序运行过程中,中断标志位因为异常而被置为true,也并不是正常的中断。

疑问2:为什么我写的中断程序没有中断呢?

1.线程中while条件的需要 自定义标志+中断标志位监测

2.抛出interruptedException异常后,中断标志位会复位,所以在catch代码块中要有重新置位   

Thread.currentThread().interrupt();

注意:在主线程中调用

th.cancel();

cancel方法中System.out.println("Thread.currentThread:"+Thread.currentThread().getName());

Thread.currentThread()对象是主线程(main)--------调用th.cancel()代码的线程,而并不是th这个线程。

三.不可中断的阻塞,是不响应interrupte中断的,如何让其响应普通的中断?

java中不可中断的有IO通讯中的inputStream/outputStream的read/write方法,NIO中selector.select()等。

解决方式:在声明线程中,覆写interrupt()方法,首先关闭底层的套接字,再调用super.interrupt(),因为在关闭套接字的时候,会像interruptedException一样抛出一个异常,我们可以捕获这个异常来进行处理。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值