多线程的终止方法
多线程的终止共有3种方法
- run方法执行结束,正常退出
- 异常终止
- 暴力终止
停止线程
停止线程是多线程中的一个重要技术点,本篇文章将对线程的停止操作进行详细讲解。
Thread类中是有一个方法 interrupt() ,虽然该方法命名为“终止”,但是它并不会立马终止当前线程,它只令当前线程终止状态为true。
停止线程不能像for或while循环中使用break停止那样直接,而是需要一些技巧来终止。
如何判断线程已终止
Thread类中提供了两个方法:
- public static boolean interrupted()
- public boolean isInterrupted()
两者的区别如下:
interrupted方法是测试当前线程是否已经中断,当前线程指运行该方法的线程。执行后具有将状态标志清除为false的功能。也就是说在第一次调用成功停止之后,第二次调用该方法就会返回false。
isInterrupted方法是测试线程Thread对象是否已经是中断状态,但不清除状态标志。
异常终止
这个方法的意思就是在判断到线程终止标志为真后,抛出异常终止当前线程。
示例代码如下:
public class Test {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(1000);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyThread extends Thread {
@Override
public void run() {
try {
for (int i = 0 ; i < 1000000 ; i++) {
if (this.interrupted()) {
System.out.println("为停止状态!线程退出!");
throw new InterruptedException();
}
System.out.println("i -- " + i);
}
System.out.println("for 循环之下的代码");
} catch (InterruptedException e) {
System.out.println("进入catch代码块,线程结束执行正常");
e.printStackTrace();
}
}
}
运行结果如下:
我们可以看到,线程成功中止。
暴力终止
暴力终止其实就是使用Thread类中的 stop() 方法,这种终止线程的方法是直接终止当前线程,有安全隐患。
示例代码:
public class Test {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
thread.sleep(100);
thread.stop();
System.out.println("finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0 ; i < 1000000 ; i++) {
System.out.println("i -- " + i);
}
}
}
运行结果:
我们会发现这里System.out.println("i – " + i);语句甚至都没有执行结束,我的线程就已经结束并回到了主方法中执行后续语句了。
暴力终止出现的问题
stop()方法会抛出java.lang.ThreadDeath异常
通常情况下可以不显式地捕捉此异常,下面是测试项目:
public class Test {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
public class MyThread extends Thread {
@Override
public void run() {
try {
this.stop();
} catch (ThreadDeath e) {
System.out.println("抛出ThreadDeath");
e.printStackTrace();
}
}
}
stop()方法会对锁定对象“解锁”
使用 stop() 会释放锁,而释放锁将会对数据造成不同步的非线程安全问题,如果出现此现象,程序处理的数据就会被破坏,最终导致程序出错。这里博主就不演示了,大家记住就好,stop方法也在JDK中已经被标注过期,因此我们在开发时也不会使用这个方法来进行线程终止的操作。
使用return终止线程
结合interrupt()和return是可以有效终止线程的,但是不提倡使用这个方法,代码中可能出现多个return,逻辑有可能会变得复杂,最重要的是这样会造成污染。
总结
由上面的例子我们可以得出,在项目开发的过程中,如果有要对线程进行终止操作的需求时,尽可能地去使用interrupt()方法+抛异常的方法进行终止线程,其他的方法一般都不推荐,毕竟其他方法多多少少都是有些问题的。