线程中断

线程中断就是处于运行状态的线程被强制打断。线程中断总体来说有三种方法:正常退出、stop暴力停止、interrupt异常停止。其中使用stop()方法是不安全的,可能导致数据不同步或者资源无法回收,目前stop()方法已经被标注为作废方法。一般使用interrupt停止线程,这里有几个与之相关的方法:

public void interrupt() {} // 中断线程

public boolean isInterrupted(){} // 查看线程中断状态

我们来使用一下看看效果:

class MyThread7 extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			System.out.println(i);
		}	
	}
}

public class Interrupt {

	public static void main(String[] args) throws InterruptedException {

		MyThread7 thread = new MyThread7();

		thread.start();
		System.out.println(thread.getName() + "线程的中断状态:" + thread.isInterrupted());
		thread.interrupt(); // 由主线程中断了一个子线程
		System.out.println(thread.getName() + "线程的中断状态:" + thread.isInterrupted());

	}

}

多运行几次会发现,run()方法中的100次循环全部执行完了,线程好像并没有中断,并且可以看到打印的线程状态是不同的:

Thread-0线程的中断状态:false

Thread-0线程的中断状态:true

打印的线程状态有所变化,但是线程好像又没有中断,这是为什么呢?实际上,interrupt并不能真正的停止线程,只是更换了线程状态标志。

 

 

在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 "。这句话启发了我们如何正确的中断一个线程,中断一个线程的本质就是中断run()方法的执行,也就是说run()不再执行后,这个线程就结束了。所以,通过中断状态标志位来控制run()方法中逻辑代码的运行,就可以很好的保证线程的中断。比如这样做:

public void run(){    
        try{    
             ....    
             while(!Thread.currentThread().isInterrupted() && more work to do) {    
                    // do more work; 
             }   
        } catch(InterruptedException e) {    
                    // thread was interrupted during sleep or wait    
        } finally {    
                   // cleanup, if required    
        }    
}    

这里的while循环不断的检查中断状态,一旦状态转为true,也就是执行了interrupt方法,那么逻辑代码不再执行。

 

 

上面所说的情况是线程在运行状态时被中断所要做的处理,那么如果线程在阻塞状态被中断会怎样?我们在sleep方法中看到过,它抛出了一个InterruptedException,当一个线程使用了sleep方法(wait、join)处于阻塞状态时,再使用interrupt就会触发sleep方法抛出InterruptedException异常(实际上是给阻塞的线程发出中断信号,阻塞线程检查到中断标识),进而导致线程中断。比如这样做:

class MyThread7 extends Thread {

	@Override
	public void run() {
		try {
			Thread.sleep(20000); // 子线程睡眠
		} catch (InterruptedException e) {
			e.printStackTrace();
		}	
	}
}

public class Interrupt {

	public static void main(String[] args) throws InterruptedException {

		MyThread7 thread = new MyThread7();

		thread.start();
		thread.interrupt(); // 由主线程中断了一个子线程
	}
}

 

 

补充:interrupted()方法,作用是测试当前线程是否已经中断,线程的中断状态也是由该方法清除。

public class Interrupt {

	public static void main(String[] args) throws InterruptedException {

		Thread.currentThread().interrupt();
		
		System.out.println(Thread.currentThread().getName() + "线程的中断状态:" + Thread.currentThread().interrupted());
		System.out.println(Thread.currentThread().getName() + "线程的中断状态:" + Thread.currentThread().interrupted());
	}

}

main线程的中断状态:true
main线程的中断状态:false

主线程被打断,使用interrupted()方法查看中断状态,发现标志位改为了true;再次使用interrupted()查看中断状态,发现标志位改为false。在第一次使用interrupted()方法时,它返回标志位,同时清除标志位(置为false),导致下一次的返回值变为false。所以interrupted()方法有清除标志位的功能。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值