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

硅谷探秘者 2454 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基础 4727 java启动线三种1.继承Thread类,重写run法,调用start法启动线2.实现Runnable接口,重写run法,调用start法启动线3.实现Callable接口代码如
java基础 2075 非守护线结束时,序也就,同时会杀死进所有守护线。反过来说,只要任何非守护线还在运行,序就不会。守护线和用户线没啥本质区别:唯一不同之处就在于虚拟机离开:如果用户线
java基础 3751 线恢复等基础功能都需要依赖个计数器来完成。  由于Java虚拟机线是通过线轮流切换、分配处理器执行时间来实现,在任何一个时刻,一个处理器(对于多核处理器来说是一个内核)都只
official 1110 线五种基本状态:初始化、可运行、运行、阻塞、阻塞状态分为:等待阻塞、同步阻塞、其他阻塞三种等待阻塞:调用某锁对象wait法可使当前线进入等待阻塞状态,并且该线放弃所有资源(包括
java基础 1508 java线通讯之生产者消费者模生产者消费者模是并发、多线中经典设计模,生产者和消费者通过分离执行工作解耦,简化开发模,生产者和消费者可以以不同速度生产和消费数据。一个生产和消
java基础 3352 ”。线对象创建后,其它线调用该对象start()法,从而来启动该线。例如,thread.start()。处于就绪状态线,随时可能CPU调度执行。3.运行状态(Running):线获取C
java基础 3113 为什线池:1.创建/销毁线伴随着系统开销,过于频繁创建/销毁线,会很大度上影响处理效率2.线并发数量过多,抢占系统资源从而导致阻塞3.对线进行一些简单管理
java基础 1909 下面就以两个法为主展开讨论。首先说明者两个作用: wait():使调用该线释放该同步锁资源,然后从运行状态退出,进入等待队列,直到再次唤醒。 notify():随机唤醒等待队列中等待
归档
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 2021-12  14 2022-01  7 2022-05  1 2022-08  3 2022-09  2 2022-10  2 2022-12  5 2023-01  3 2023-02  1 2023-03  4 2023-04  2 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1 2024-04  1 2024-08  1
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job rabbitmq haproxy srs 音视频 webrtc javascript 加密算法
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。