多线程编程中耗时线程是很常见的情况,有时候我们不得不在一个线程中去终止另一个耗时线程。JDK并不推荐直接停止比如this.stop(),这会导致一些异常,比如锁未释放程序一直死锁。JDK推荐使用一个线程去通知耗时线程该结束线程了,耗时线程做退出前的回收处理然后自己结束线程。
自定义标志位终止
使用volatile 修饰的变量isExit控制线程的退出,这种方法需要不断及时判断isExit的值
public classFinishThreadLearn {public static void main(String[] args) throwsInterruptedException {
InterruptStopThread threadA= new InterruptStopThread("A");
threadA.start();
Thread.sleep(100);
System.out.println("终止线程");
threadA.isExit=true;
}
}class InterruptStopThread extendsThread {privateString name;public volatile boolean isExit = false;publicInterruptStopThread(String name) {this.name =name;
}
@Overridepublic voidrun() {super.run();while (!isExit) {
System.out.println("Thead:" + this.name + "正在运行");
}
System.out.println("线程结束运行");
}
}
输出结果可以看到,线程并未立即终止,结束循环体后才最终结束线程。
interrupt() 方式终止
正常执行的代码
public classFinishThreadLearn {public static void main(String[] args) throwsInterruptedException {
InterruptStopThread threadA= new InterruptStopThread("A");
threadA.start();
Thread.sleep(100);
System.out.println("终止线程");
threadA.interrupt();
}
}class InterruptStopThread extendsThread {privateString name;public volatile boolean isExit = false;publicInterruptStopThread(String name) {this.name =name;
}
@Overridepublic voidrun() {super.run();while (!isInterrupted()) {
System.out.println("Thead:" + this.name + "正在运行");
}
System.out.println("线程结束运行");
}
}
执行结果
处于阻塞休眠的代码
这里有点不一样,interrupt()方式中断阻塞会把标志位清除并报出InterruptedException异常,所以要在catch的时候退出。
public classFinishThreadLearn {public static void main(String[] args) throwsInterruptedException {
InterruptStopThread threadA= new InterruptStopThread("A");
threadA.start();
Thread.sleep(2000);
System.out.println("终止线程");
threadA.interrupt();
}
}class InterruptStopThread extendsThread {privateString name;public volatile boolean isExit = false;publicInterruptStopThread(String name) {this.name =name;
}
@Overridepublic voidrun() {super.run();while (true) {
System.out.println("Thead:" + this.name + "正在运行");try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();break;
}
}
System.out.println("线程结束运行");
}
}
执行结果
stop()强行停止
public classFinishThreadLearn {public static void main(String[] args) throwsInterruptedException {
InterruptStopThread threadA= new InterruptStopThread("A");
threadA.start();
Thread.sleep(100);
System.out.println("终止线程");
threadA.stop();
}
}class InterruptStopThread extendsThread {privateString name;public volatile boolean isExit = false;publicInterruptStopThread(String name) {this.name =name;
}
@Overridepublic voidrun() {super.run();while (!isInterrupted()) {
System.out.println("Thead:" + this.name + "正在运行");
}
System.out.println("线程结束运行");
}
}
从执行结果可以看到,run方法并未完全执行完就结束了,所以这种方法不推荐使用
源码分析
Thread源码中使用了一个volatile修饰的标志位控制终止信号
public class Thread implementsRunnable {
.../*Interrupt state of the thread - read/written directly by JVM*/
private volatile booleaninterrupted;
...
}
interrupt方法会使标志位变为true
判断线程是否终止JDK提供了两种方式
Thread.interrupted():测试当前线程是否已经中断this.isInterrupted():测试线程是否已经中断
this.isInterrupted()
调用isInterrupted会返回该标志位
Thread.interrupted()
调用interrupted会返回该标志位,如果为ture会将标志位清空,且这个方法为静态方法