interrup(线程中断)深入理解

线程中断

定义

Java中的线程中断是一种线程间的协作模式,通过设置线程的中断标志并不能直接终止该线程的执行,而是被中断的线程根据中断状态自行处理。

方法

  1. void interrupt ()方法: 中断线程,例如当A线程运行时,线程B可以调用线程A的interrupt()方法来设置线程A的中断标志为 true 并立即返回。设置标志仅仅是设置标志,其实线程A并没有被中断,它还会继续往下执行。如果线程A因为调用了 wait() 、sleep()、jion()方法而被阻塞,这时候若B线程调用了A线程的interrupt() 方法,线程A会在调用这些方法的地方抛出InterruptedException异常而返回。
  2. boolean isInterrupted()方法: 检查当前线程是否被中断,如果是返回 true,否者返回 false
public boolean isInterrupt(){
	//传递false,说明不清除中断标志
	return isInterrupt(false);
}
  1. boolean interrupted()方法: 检测当前线程是否被中断,如果是返回true,否者返回false。与 isInterrupted() 方法不同的是,该方法如果发现当前线程被中断,则会清除中断标志,并且该方法是 static 方法,可以通过 Thread 直接调用,从它的源代码我们可以看到,在 interrupted() 方法内部是获取当前调用线程的中断标志,而不是调用 interrupted() 方法的实例对象的中断标志。
public boolean interrupted(){
   //清除中断标志
   return currentThread().isInterrupted(true);
} 

举例

  1. 下面看一个使用interrupted() 方法优雅退出的经典例子
public void run(){
   try{
   		...
   		while( !Thread.currentThread().isInterrupted() && more work to do ){
   		//do more work
   	}catch(InterruptedException e){
   			//这里是线程在阻塞期间然后又调用interrupt()方法之后抛出异常	
   	}
   	finally{
   			//做其他的一些事
   	}
}

2、现在我们再来看一个根据中断标志来判断线程时候终止的例子

public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) {
                    System.out.println(Thread.currentThread()+"hello!");
                }
            }
        });

        thread.start();


        //让主线程休眠一秒,使中断前让子线程输出
        Thread.sleep(1000);

        System.out.println("main thread interrupt thread");
        thread.interrupt();
        thread.join();
        System.out.println("main is over!!");
    }

运行结果如下:
在这里插入图片描述
3、我们再来看一种情况,当线程为了等待一些特定的条件的到来时,一般会调用 sleep 方法、wait 方法或者 join 方法来阻塞挂起当前线程。比如一个线程调用了 sleep(3000),那么调用线程就会被阻塞3秒。但是有时候可能在3秒内条件已经满足了,如果一直等到3秒后返回有点浪费时间,这个时候我们可以调用线程的 interrupt() 方法来强制性的让sleep() 方法抛出 InterruptedException 异常而返回,让线程恢复到激活状态。

public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("线程开始休眠3000秒了");
                    Thread.sleep(3000000);
                    System.out.println("线程休眠好了");
                } catch (InterruptedException e) {
                    System.out.println("线程休眠时调用了因interrupt()方法抛出异常了!!!");
                }
                System.out.println("线程被唤醒了");

            }
        });

        thread.start();


        //让主线程休眠一秒,确保子线程进入休眠
        Thread.sleep(1000);

        System.out.println("main thread interrupt thread");
        thread.interrupt();
        thread.join();
        System.out.println("main thread is over!!");
    }

运行结果:
在这里插入图片描述

interrupted() 与 isInterrupted() 方法的不同之处

奥义之处:通过他们两个方法的源码我们可以知道,interrupted() 方法它是检测当前线程是否被中断,如果是的话,则会清除中断标志,而 isInterrupted() 方法不会清除中断标志;而且 interrupted() 方法它是获取当前调用线程的中断标志,而不是调用 interrupted() 方法的实例对象的中断标志。(这里理解可能会比较饶)
打个比方来说:在我们一个类的mian方法里面我们创建了一个子线程 threadOne ,然后我们在main方法里面我们调用了 threadOne .interrupte() 方法来给 thread 线程设置中断标志,之后我们再在main方法里面调用 threadOne .isInterrupted()、threadOne .interrupted()、Thread.isInterrupted()、threadOne .isInterrupted() 这四个方法返回的结果将会是true、false、flase、true
注意:interrupted() 方法是一个static方法, isInterrupted() 方法是一个普通方法

    public static void main(String[] args) throws InterruptedException {
        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                for (; ; ) {

                }

            }
        });

        threadOne.start();


        System.out.println("main thread interrupt thread");

        Thread.currentThread().interrupt();//主线程设置了中断标志

        System.out.println(threadOne.isInterrupted());
        System.out.println(Thread.currentThread().isInterrupted());
        System.out.println(threadOne.interrupted()); //这步清除了主线程的中断标志
        System.out.println(Thread.currentThread().isInterrupted());
        threadOne.join();
        System.out.println("main thread is over!!");
    }

运行结果:
在这里插入图片描述
== 改进上面的例子如下==

    public static void main(String[] args) throws InterruptedException {
        Thread threadOne = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().interrupted()) {

                }

                System.out.println("threadOne isInterrupted:"+Thread.currentThread().isInterrupted());

            }
        });

        threadOne.start();


        System.out.println("main thread interrupt thread");

        //设置中断标志
        threadOne.interrupt();
        
        threadOne.join();
        System.out.println("main thread is over!!");
    }

运行结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值