java线程正确的终止方式【被interrupt迷惑了这么久】

硅谷探秘者 1429 0 0

java线程中关于中断的三个重要方法

interrupt(),isInterrupted()和interrupted()

解释:

        interrupt():调用某线程的interrupt()方法会改变当前线程的中断状态,但是不会终止当前线程的运行,那么此线程终止不终止还是取决于线程中的代码。

        isInterrupted():该方法用来判断某线程的终端状态,返回true/false

        interrupted():该方法用于检测中断并清除中断状态,注意该方法为静态方法,只作用于当前线程


interrupt()方法

        注意不要被interrupt方法迷惑,interrupt方法不能终止正常执行的程序,而只是会改变该线程的中断状态而已,就像线程中的一个属性一样(只是比喻而已,其实一点也不一样)。它和Thread.stop方法完全不一样,Thread.stop确实停止了一个正在运行的线程,然而,这种方法是不安全也是不受提倡的。

代码案例:

public class ExamApplicationTests{	
	static volatile boolean stop;	
	public static void main(String[] args) {
		Thread t=new Thread(new Runnable() {
			@Override
			public void run() {
				while(!stop) {
					System.out.println("running...");
					long time = System.currentTimeMillis();
	            	while((System.currentTimeMillis()-time < 1000)) {
	            		//延时一秒
	            	}
				}
			}
		});
		t.start();
		t.interrupt();
		System.out.println("中断线程"+t.isInterrupted());
	}	
}

程序输出:

中断线程true
running...
running...
running...
running...
running...
running...
...

由此可以看出interrupt方法并没有终止线程的执行。


如何终止一个线程

        中断线程最好的,最受推荐的方式是,使用共享变量发出信号,告诉线程必须停止正在运行的任务。然而线程必须周期性的核查这一变量,然后有秩序地中止任务。

例:

public class ExamApplicationTests{	
	static volatile boolean stop;	
	public static void main(String[] args) throws InterruptedException {
		Thread t=new Thread(new Runnable() {
			@Override
			public void run() {
				while(!stop) {
					System.out.println("running...");
					long time = System.currentTimeMillis();
	            	while((System.currentTimeMillis()-time < 1000)) {
	            		//延时一秒
	            	}
				}
				System.out.println("线程结束");
			}
		});
		t.start();
		Thread.sleep(3000);
		stop=true;
	}	
}

程序输出:

running...
running...
running...
线程结束



interrupt存在的意义是什么?

        刚才说过可以用共享变量的方式终止线程,但前提是该线程必须周期性的核查这一变量。那么就要考虑,如果当前线程正在处于阻塞状态怎么办?那么此时执行interrupt方法就变得有意义了,如果线程执行interrupt方法时,该线程处于Thread.sleep(), Thread.join()或 Object.wait()这三种阻塞状态,那么该线程将取消阻塞,并且抛出InterruptedException异常,那么我们就有机会在捕获异常后处理终止任务的逻辑。

例:

public class ExamApplicationTests{	
	static volatile boolean stop;	
	public static void main(String[] args) throws InterruptedException {
		Thread t=new Thread(new Runnable() {
			@Override
			public void run() {
				//任务逻辑
				try {
					Thread.sleep(10000);//睡眠10秒,处于阻塞状态
				} catch (InterruptedException e) {
					e.printStackTrace();
					System.out.println("任务终止");	
					return ;
				}
				//其他任务逻辑...
				System.out.println("线程结束");
			}
		});
		t.start();
		System.out.println("Thread start");
		t.interrupt();
		System.out.println("Thread end");
		stop=true;
	}	
}

程序输出:

Thread start
Thread end
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.dzqc.exam.ExamApplicationTests$1.run(ExamApplicationTests.java:12)
	at java.lang.Thread.run(Unknown Source)
任务终止

可以通过这种方式提早的结束线程的阻塞状态,从而执行终止逻辑。



猜你喜欢
java基础 2332 java启动线三种1.继承Thread类,重写run法,调用start法启动线2.实现Runnable接口,重写run法,调用start法启动线3.实现Callable接口代码如
java基础 2626 线恢复等基础功能都需要依赖个计数器来完成。  由于Java虚拟机线是通过线轮流切换、分配处理器执行时间来实现,在任何一个时刻,一个处理器(对于多核处理器来说是一个内核)都只
java基础 931 非守护线结束时,序也就,同时会杀死进所有守护线。反过来说,只要任何非守护线还在运行,序就不会。守护线和用户线没啥本质区别:唯一不同之处就在于虚拟机离开:如果用户线
official 131 线五种基本状态:初始化、可运行、运行、阻塞、阻塞状态分为:等待阻塞、同步阻塞、其他阻塞三种等待阻塞:调用某锁对象wait法可使当前线进入等待阻塞状态,并且该线放弃所有资源(包括
java基础 402 java线通讯之生产者消费者模生产者消费者模是并发、多线中经典设计模,生产者和消费者通过分离执行工作解耦,简化开发模,生产者和消费者可以以不同速度生产和消费数据。一个生产和消
java基础 1118 ”。线对象创建后,其它线调用该对象start()法,从而来启动该线。例如,thread.start()。处于就绪状态线,随时可能CPU调度执行。3.运行状态(Running):线获取C
java基础 577 下面就以两个法为主展开讨论。首先说明者两个作用: wait():使调用该线释放该同步锁资源,然后从运行状态退出,进入等待队列,直到再次唤醒。 notify():随机唤醒等待队列中等待
official 100 问题,那netty就对解决个问题提供线解决案。netty线模型实际上Netty线模型就是Reactor模一个实现,而Reactor模又是什呢?Reactor模是基于事件
归档
2018年11月  12 2018年12月  33 2019年01月  28 2019年02月  28 2019年03月  32 2019年04月  27 2019年05月  33 2019年06月  6 2019年07月  12 2019年08月  12 2019年09月  21 2019年10月  8 2019年11月  15 2019年12月  25 2020年01月  9 2020年02月  5 2020年03月  16 2020年04月  4 2020年06月  1 2020年07月  7 2020年08月  13 2020年09月  9 2020年10月  5 2020年12月  3 2021年01月  1 2021年02月  5 2021年03月  7 2021年04月  4 2021年05月  4 2021年06月  1 2021年07月  7 2021年08月  2 2021年09月  8 2021年10月  9 2021年11月  16
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议
目录
祝愿神州十三飞行乘组平安归来