[Java] 线程中断(三)

       前两篇文章分别说明了线程应该由它自己来处理中断和运行中的线程如何自己处理中断,本文主要描述阻塞中的线程如何自己处理中断。线程阻塞其实就是在执行过程中,为了某些条件或基于别的什么原因,自愿的或被迫的暂定一定的时间,然后条件满足后再继续执行。查阅一下线程类,发现使线程阻塞的方法就这么几个:最常用的是sleep,让线程休眠一定的时间,时间过后再继续执行;其次是wait,让线程在一定时间内等待,直到被通知或超时就继续执行;然后是join,官方解释是等待该线程的终止,其实可以用来协调线程间执行顺序的问题。或当一个线程执行完或超时后线程继续往下执行。

       现在已明白了线程的阻塞情况,线程在阻塞时,说明JVM没有运行它,这时调用线程的interrupt()方法,线程会有反应吗,如果有的话会是什么反应呢。按照常规的理解,线程当前都暂停执行了,对它调用中断操作,应该没有响应才对。但是稍微想一想,就觉得这种情况不合理。假设一个场景,一个线程已经持有了一部分资源,又为了某个资源不到位,进入了等待或阻塞,这个等待也许会比较漫长,这时突然环境发生了变化,我们已经不需要这个线程再继续运行了,我们需要其它的线程开始运行,现在就需要把这个线程中断掉,我们现在调用了线程中断方法。对于线程的响应,我们做一下假设,假设一:线程继续阻塞直到超时或获得了资源时,才被重新调度执行,发现自己被中断了,然后自己执行中断处理,线程结束掉。假设二:线程永不超时,但是环境已变,可能永远等不来想要的资源。这样线程一直阻塞,已持有的资源也无法释放,就造成了死锁。对于以上两种假设,在实际当中都不应该是合理的。合理的情况应该是,即使线程处于阻塞状态,也应该能够快速的响应中断操作,事实上就是这样的。

       线程阻塞时,对于我们来说就是停下来不在执行。但是JVM对线程的信息要掌握的多,它还是在监视着线程的情况,这时如果出现中断,仍能够快速得到响应。线程在阻塞时遇到中断,JVM的做法是,先设置线程的状态为中断,然后再阻塞语句处直接抛出一个InterruptedException异常,然后再清除刚才设置的中断状态。我们可以捕获这个异常,做一些清理工作,然后退出线程,线程已及它的资源被释放掉。

下面是简单的示例代码:

Thread t1 = new Thread(new Runnable(){
			public void run() {
				System.out.println("线程开始执行...");
				
				try {
					System.out.println("线程开始休眠4秒...");
					Thread.sleep(4000);
					System.out.println("线程结束休眠4秒...");
				} catch (InterruptedException e) {
					System.out.println("线程发生异常...");
					System.out.println("线程,state:" + Thread.currentThread().getState() + ", alive:" + Thread.currentThread().isAlive() + ", interrupt: " + Thread.currentThread().isInterrupted());
				}
				
				System.out.println("线程继续执行...");
			}});
		
		System.out.println("线程未启动,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		t1.start();
		System.out.println("线程已启动,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		System.out.println("主线程休眠1秒钟,开始");
		Thread.sleep(1000);
		System.out.println("主线程休眠1秒钟,结束");
		System.out.println("线程在休眠,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		t1.interrupt();
		System.out.println("线程被中断,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		System.out.println("主线程休眠5秒钟,开始");
		Thread.sleep(5000);
		System.out.println("主线程休眠5秒钟,结束");
		System.out.println("线程已结束,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());


下面是运行的结果:

线程未启动,state:NEW, alive:false, interrupt: false
线程已启动,state:RUNNABLE, alive:true, interrupt: false
主线程休眠1秒钟,开始
线程开始执行...
线程开始休眠4秒...
主线程休眠1秒钟,结束
线程在休眠,state:TIMED_WAITING, alive:true, interrupt: false
线程被中断,state:TIMED_WAITING, alive:true, interrupt: true
主线程休眠5秒钟,开始
线程发生异常...
线程,state:RUNNABLE, alive:true, interrupt: false
线程继续执行...
主线程休眠5秒钟,结束
线程已结束,state:TERMINATED, alive:false, interrupt: false

       线程还没启动时,它的状态是NEW,没有存活,没有中断。线程启动后,状态为RUNNABLE,存活,没有中断。主线程休眠一秒钟,为了让子线程进入四秒休眠。主线程结束休眠后,子线程还在休眠,这时线程的状态是TIMED_WAITING,存活,没有中断。然后调用中断,子线程状态为TIMED_WAITING,存活,但是已经中断了。主线程进入休眠,接着子线程里面发生了异常,我们捕获了异常,线程的状态又变为RUNNABLE,存活,中断被清除了,子线程继续运行。当主线程结束休眠时,子线程早已结束,所以状态为TERMINATED,已经不再存活,当然也不中断。

下面是一个简单示例:

Thread t1 = new Thread(new Runnable(){
			public void run() {
				System.out.println("线程开始执行...");
				
				try {
					System.out.println("线程开始等待4秒...");
					synchronized(Thread.currentThread()) {
						Thread.currentThread().wait(4000);
					}
					System.out.println("线程结束等待4秒...");
				} catch (InterruptedException e) {
					System.out.println("线程发生异常...");
					System.out.println("线程,state:" + Thread.currentThread().getState() + ", alive:" + Thread.currentThread().isAlive() + ", interrupt: " + Thread.currentThread().isInterrupted());
				}
				
				System.out.println("线程继续执行...");
			}});
		
		System.out.println("线程未启动,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		t1.start();
		System.out.println("线程已启动,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		System.out.println("主线程休眠1秒钟,开始");
		Thread.sleep(1000);
		System.out.println("主线程休眠1秒钟,结束");
		System.out.println("线程在休眠,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		t1.interrupt();
		System.out.println("线程被中断,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		System.out.println("主线程休眠5秒钟,开始");
		Thread.sleep(5000);
		System.out.println("主线程休眠5秒钟,结束");
		System.out.println("线程已结束,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());


下面是运行结果:

线程未启动,state:NEW, alive:false, interrupt: false
线程开始执行...
线程已启动,state:RUNNABLE, alive:true, interrupt: false
线程开始等待4秒...
主线程休眠1秒钟,开始
主线程休眠1秒钟,结束
线程在休眠,state:TIMED_WAITING, alive:true, interrupt: false
线程被中断,state:TIMED_WAITING, alive:true, interrupt: false
线程发生异常...
主线程休眠5秒钟,开始
线程,state:RUNNABLE, alive:true, interrupt: false
线程继续执行...
主线程休眠5秒钟,结束
线程已结束,state:TERMINATED, alive:false, interrupt: false

下面是一个示例:

 

Thread t1 = new Thread(new Runnable(){
			public void run() {
				System.out.println("线程开始执行...");
				
				Thread t = new Thread(new Runnable(){
					public void run() {
						System.out.println("join线程运行...");
						try {
							Thread.sleep(5000);
						} catch (InterruptedException e) {
						
						}
					}});
				
				try {
					System.out.println("线程开始join 4秒...");
					t.start();
					t.join(4000);
					System.out.println("线程结束join 4秒...");
				} catch (InterruptedException e) {
					System.out.println("线程发生异常...");
					System.out.println("线程,state:" + Thread.currentThread().getState() + ", alive:" + Thread.currentThread().isAlive() + ", interrupt: " + Thread.currentThread().isInterrupted());
				}
				
				System.out.println("线程继续执行...");
			}});
		
		System.out.println("线程未启动,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		t1.start();
		System.out.println("线程已启动,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		System.out.println("主线程休眠1秒钟,开始");
		Thread.sleep(1000);
		System.out.println("主线程休眠1秒钟,结束");
		System.out.println("线程在休眠,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		t1.interrupt();
		System.out.println("线程被中断,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());
		System.out.println("主线程休眠5秒钟,开始");
		Thread.sleep(5000);
		System.out.println("主线程休眠5秒钟,结束");
		System.out.println("线程已结束,state:" + t1.getState() + ", alive:" + t1.isAlive() + ", interrupt: " + t1.isInterrupted());


下面是运行结果:

线程未启动,state:NEW, alive:false, interrupt: false
线程已启动,state:RUNNABLE, alive:true, interrupt: false
主线程休眠1秒钟,开始
线程开始执行...
线程开始join 4秒...
join线程运行...
主线程休眠1秒钟,结束
线程在休眠,state:TIMED_WAITING, alive:true, interrupt: false
线程发生异常...
线程被中断,state:RUNNABLE, alive:true, interrupt: false
线程,state:RUNNABLE, alive:true, interrupt: false
主线程休眠5秒钟,开始
线程继续执行...
主线程休眠5秒钟,结束
线程已结束,state:TERMINATED, alive:false, interrupt: false

     上面三个示例其实基本一样,每次运行的结果,打印的先后顺序不完全一样。

如文章里有错误,敬请指出,共同讨论!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值