java中如何终止线程的执行
线程被创建后,当run()方法执行完毕,线程便会正常结束和销毁。但是,在有些情况下,run() 方法是永远不会执行完的,比如在run()方法中进行while()轮询任务时,这种情况下就需要我们通过代码手动的退出线程。
这里我们介绍以下几种方法:
1. 使用退出标识
添加一个boolean类型的变量isRun作为线程的退出标识,当isRun为false时,结束循环以中断线程。
public class CloseThread {
public static class CreateThread extends Thread {
//定义退出标志,true一直执行,false退出循环
public volatile boolean isRun = true;
@Override
public void run() {
System.out.println("创建线程完成");
while (isRun) {
System.out.println("工作中..., thread name =" + Thread.currentThread().getName());
SleepUtils.second(1);//线程停止1秒
}
System.out.println("创建执行完毕");
}
public void interrupt() {
System.out.println("中断标识设置为false");
this.isRun = false;
}
}
public static void main(String[] args) {
//实例化一个线程并 start()
Thread thread = new CreateThread();
thread.start();
//线程停止5秒
SleepUtils.second(5);
System.out.println("尝试中断线程");
thread.interrupt();
}
}
执行代码,打印以下结果:
创建线程完成
工作中..., thread name =Thread-0
工作中..., thread name =Thread-0
工作中..., thread name =Thread-0
工作中..., thread name =Thread-0
工作中..., thread name =Thread-0
开始尝试中断线程
中断标识设置为false
线程执行完成
在main()中调用interrupt(),设置线程的中断标识为false,最终成功结束了循环中断了线程的执行。
2. 调用线程本身的interrupt()方法
interrupt()方法是线程本身的一种中断标识,通过调用这个方法可以将线程的isInterrupted()设置为true。
public class CloseThread2 {
public static class CreateThread2 extends Thread {
@Override
public void run() {
while (!currentThread().isInterrupted()) {
System.out.println("工作中...");
}
System.out.println("线程执行完成");
}
}
public static void main(String[] args) {
//实例化一个线程并start()
CreateThread2 thread = new CreateThread2();
thread.start();
//当前线程停止1s
SleepUtils.second(1);
//调用线程的interrupt()
thread.interrupt();
System.out.println("中断线程,thread " + thread.getId() + " :" + thread.isInterrupted());
}
}
执行代码,打印以下结果:
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
工作中...
中断线程,thread 11 :true
线程执行完成
在main()中调用线程本身的interrupt(),设置线程的中断标识isInterrupted()为true,最终成功结束了循环中断了线程的执行。
但是使用interrupt()时需要注意线程是否处于阻塞状态。当对处于阻塞状态的线程调用interrupt()方法时,会抛出InterruptException异常,而这个异常会清除中断标识,也就是会将中断标识重新修改为false。
我们可以通过以下代码来模拟这种情况:
public class CloseThread3 {
public static class CreateThread3 extends Thread {
@Override
public void run() {
System.out.println("thread 已创建" + currentThread().getId() + " :" + currentThread().isInterrupted());
while (!currentThread().isInterrupted()) {
System.out.println("工作中...");
try {
//线程暂停3秒,模拟处于阻塞状态
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("抛出异常,thread " + currentThread().getId() + " :" + currentThread().isInterrupted());
}
}
System.out.println("线程执行完成");
}
}
public static void main(String[] args) {
CreateThread3 thread = new CreateThread3();
thread.start();
//当前线程暂停5秒
SleepUtils.second(5);
System.out.println("开始尝试中断线程");
//调用线程的interrupt()
thread.interrupt();
System.out.println("中断线程,thread " + thread.getId() + " :" + thread.isInterrupted());
}
}
执行代码,打印以下结果:
thread 已创建11 :false
工作中...
工作中...
开始尝试中断线程
中断线程,thread 11 :false
抛出异常,thread 11 :false
工作中...
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at threadDemo.CloseThread3$CreateThread2.run(CloseThread3.java:15)
工作中...
工作中...
工作中...
.........(不断的打印工作中...)
由此可见,当线程处于阻塞状态中,调用线程的interrupt()将线程的中断标识isInterrupted()设置为,但是当抛出InterruptException异常时,会清除中断标识,将中断标识重新修改为false,导致线程并不会被终止,而是一直执行下去。
为了解决这种情况,我们可以将本文所讲的这两种中断线程的方法组合使用,为线程添加一个中断标识变量,并且重写interrupt()方法:
public class CloseThread4 {
public static class CreateThread4 extends Thread {
//定义退出标志,true会一直执行,false会退出循环
public volatile boolean isRun = true;
@Override
public void run() {
System.out.println("thread 已创建" + currentThread().getId() + " :" + currentThread().isInterrupted());
while (isRun && !currentThread().isInterrupted()) {
System.out.println("工作中...");
try {
//线程暂停3秒,模拟处于阻塞状态
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("抛出异常,thread " + currentThread().getId() + " :" + currentThread().isInterrupted());
}
}
System.out.println("线程执行完成");
}
/**
* 重写interrupt()
*/
@Override
public void interrupt() {
System.out.println("中断标识isRun设置为false");
this.isRun = false;
super.interrupt();
}
}
public static void main(String[] args) {
CreateThread4 thread = new CreateThread4();
thread.start();
//当前线程暂停5秒
SleepUtils.second(5);
System.out.println("开始尝试中断线程");
//调用线程的interrupt()
thread.interrupt();
System.out.println("中断线程,thread " + thread.getId() + " :" + thread.isInterrupted());
}
}
执行代码,打印以下结果:
thread 已创建11 :false
工作中...
工作中...
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at threadDemo.CloseThread4$CreateThread4.run(CloseThread4.java:17)
开始尝试中断线程
中断标识设置为false
中断线程,thread 11 :true
抛出异常,thread 11 :false
线程执行完成
通过自定义中断标识和线程isInterrupted()中断标识组合使用,便解决了线程处于阻塞中调用interrupt()导致isInterrupted()被清除的问题。
原文链接:http://blog.z-love.com/#/Content/Multi-threaded-creation