https://github.com/CyC2018/CS-Notes/blob/master/notes/Java%20%E5%B9%B6%E5%8F%91.md#%E4%B8%89%E4%B8%AD%E6%96%AD
一个线程执行完毕之后会自动结束,如果在运行过程中发生异常也会提前结束。
如何安全地终止线程
有2种方法可以安全地终止线程:
- 使用interrupt()
- 利用一个boolean变量来控制是否需要停止任务并终止该线程(推荐)。
interrupt()、isInterrupted()、interrupted()的区别与使用
interrupt()
注意区分interrupted()方法;
public void interrupt()
interrupt()是用于中断线程的,调用该方法的线程的状态将被置为"中断"状态。
注意:线程中断仅仅是设置线程的中断状态位,++不会停止线程++。需要用户自己去监视线程的状态为并做处理。
isInterrupted()
isInterrupted()测试线程是否已经中断。线程的 中断状态 不受该方法的影响。
public boolean isInterrupted()
interrupted()
public static boolean interrupted()
interrupted()第一次使用返回true,并清除中断标志位,在此之后查询中断状态isInterrupt()都会返回false,第一次返回的true可以跳出循环。第二次以及以后都是返回false。
区别案例
public class InterruptExample {
private static class MyThread extends Thread {
@Override
public void run() {
while (true) {
System.out.println(isInterrupted());
//interrupt()并不会中断线程,所以后面的代码会被继续执行;
interrupt();
System.out.println(isInterrupted());
//interrupted()第一次返回true,并清除标志位,所以以后查询中断状态返回的都是false
System.out.println(interrupted());
System.out.println(isInterrupted()); //false
break;
}
System.out.println("Thread end");
}
}
public static void main(String[] args){
Thread thread = new MyThread2();
thread.start();
}
}
输出
false
true
true //interrupted()第一次返回true
false
Thread end
注意
-
通过调用一个线程的 interrupt()来中断该线程,如果该线程处于阻塞、限期等待或者无限期等待状态,那么就会抛出 InterruptedException,从而提前结束该线程。但是不能中断 I/O 阻塞和 synchronized 锁阻塞。
-
suspend()、resume()和stop()过期了,不建议使用;
public class InterruptExample {
private static class MyThread1 extends Thread {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("Thread run");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new MyThread1();
thread1.start();
thread1.interrupt();
System.out.println("Main run");
}
由于线程中调用了Thread.sleep()方法,因此会抛出一个 InterruptedException,从而提前结束线程,不执行之后的语句。
Main run
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at InterruptExample.lambda$main$0(InterruptExample.java:5)
at InterruptExample$$Lambda$1/713338599.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
使用interrupt()方法终止线程
public class InterruptExample {
private static class MyThread2 extends Thread {
@Override
public void run() {
//
while (!isInterrupted()) {
// ..
}
System.out.println("Thread end");
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread2 = new MyThread2();
thread2.start();
thread2.interrupt();
}
Thread end
使用标志位终止线程
public class InterruptExample {
private static class MyThread extends Thread {
private volatile boolean on = true;
@Override
public void run() {
while (on) {
//todo
}
}
public void cancel(){
on = false;
}
}
public static void main(String[] args) {
Thread thread = new MyThread();
thread.start();
}
}
另外
Executor 的中断操作
调用 Executor 的 shutdown() 方法会等待线程都执行完毕之后再关闭,但是如果调用的是 shutdownNow() 方法,则相当于调用每个线程的 interrupt() 方法。