今天聊一下线程的终止,目前知道的是两种方式:
- 通过标志变量终止
- 通过中断标记终止
一、通过标志变量终止
通过标志变量,可以终止正在运行的线程,测试代码如下:
// 通过标记变量,退出正在运行的线程
static class Demo extends Thread{
// volatile修饰,保证每次读取的都是变量的最新值
private volatile boolean runFlag = true;
@Override
public void run() {
try {
int i = 0;
while (runFlag){
System.out.println("demo线程 getState() = "+getState()+" and i = "+i);
i++;
Thread.sleep(100);
}
}catch (InterruptedException e){
System.out.println("demo线程 抛出InterruptedException异常, getState() = "+getState());
System.out.println("demo线程 抛出InterruptedException异常, isInterrupted() = "+isInterrupted());
}
System.out.println("demo线程 :运行结束, runFlag = "+ runFlag);
}
// 停止线程
public void stopThread(){
this.runFlag = false;
System.out.println("main线程 :设置 runFlag = "+ runFlag);
}
}
public static void main(String[] args) {
// 1. 通过标记变量,停止正在运行的线程
Demo demo = new Demo();
demo.start();
System.out.println("demo线程 getState() = "+demo.getState());
// 主线程休眠50ms,让出cup给demo线程
try {
System.out.println("main线程 getState() = "+Thread.currentThread().getState());
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
demo.stopThread();
}
测试结果如下:
demo线程 getState() = RUNNABLE
main线程 getState() = RUNNABLE
demo线程 getState() = RUNNABLE and i = 0
demo线程 getState() = RUNNABLE and i = 1
demo线程 getState() = RUNNABLE and i = 2
demo线程 getState() = RUNNABLE and i = 3
demo线程 getState() = RUNNABLE and i = 4
main线程 :设置 runFlag = false
demo线程 :运行结束, runFlag = false
原理也比较容易理解,就是通过循环判断标志变量,来决定是否继续执行。
二、通过中断标记终止
主要是调用了interrupt方法,来设置线程的中断标记,然后循环判断中断标记来决定是否继续执行,测试代码:
// 通过中断标志,中断处于阻塞或运行的线程
static class Demo2 extends Thread{
@Override
public void run() {
try {
while (!isInterrupted()){
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":正在运行,i = "+i);
if (i >= 5){
Thread.sleep(1000);
// synchronized (this){
// wait();
// }
}
}
}
}catch (Exception e){
System.out.println("异常终止:");
e.printStackTrace();
}
System.out.println("demo2线程 :运行结束, getState() = "+ getState());
}
}
public static void main(String[] args) {
// 2. 通过中断标志,终止线程
Demo2 demo2 = new Demo2();
demo2.start();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
demo2.interrupt();
}
测试结果:
Thread-0:正在运行,i = 0
Thread-0:正在运行,i = 1
Thread-0:正在运行,i = 2
Thread-0:正在运行,i = 3
Thread-0:正在运行,i = 4
Thread-0:正在运行,i = 5
异常终止:
java.lang.InterruptedException: sleep interrupted
demo2线程 :运行结束, getState() = RUNNABLE
at java.lang.Thread.sleep(Native Method)
at com.thread.stop.StopThread$Demo2.run(StopThread.java:75)
调用线程的interupt方法,可以设置中断标记为true,但是,如果线程处于阻塞状态,那么就会抛出java.lang.InterruptedException异常,并且会将中断标记重置为false
判断线程是否出于中断状态,除了isInterrupted方法,还有interrupted方法,两者的区别在于:interrupted会重置中断标记为false,换句话说,对于中断的线程,第一此返回的true,那么第二次返回的就是false