中断
一个线程在执行完毕之后会自动结束,如果在运行的过程中发生异常也会提前结束。
1.InterruptedException
调用一个线程的interrupt()方法来中断该线程,如果该线程处于阻塞,有限等待,无限等待状态,那么就会抛出InterruptedException,从而提前结束该线程,但是不能中断I/O阻塞和Sychronized锁阻塞。
以下代码,启动一个线程后中断它,由于它调用了sleep()方法,所以处于有限等待状态,那么它就会抛出InterruptedException异常,从而提前结束线程,不再执行后面的语句。
public class InterruptException{
public static void main(String[]args)throws InterruptedException{
MyThread thread=new MyThread();
thread.start();
thread.interrupt();
System.out.println("haha");
}
}
class MyThread extends Thread{
@Override
public void run(){
try {
Thread.sleep(2000);
System.out.println("Thread run");
} catch (InterruptedException e) {
e.printStackTrace();//TODO: handle exception
}
}
}
haha
java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at MyThread.run(InterruptException.java:15)
Process finished with exit code 0
2.interrupted()
如果一个线程的run()方法执行一个无限循环,并且没有执行sleep()等会抛出InterruptedException的操作,那么调用interrupt()方法,就无法使线程提前结束。但是调用interrupt()方法会设置线程的中断标记(一旦方法抛出InterruptedException异常,那么jvm就会自动清除中断标记),此时调用interrupted()方法会返回true。因此在循环体中使用interrupted()方法来判断线程是否处于中断的状态,从而提前结线程。
public class InterruptExemple{
private static class MyThread extends Thread{
@override
public void run(){
while(!interrupted()){
//...
}
System.out.println("Thread end");
}
}
public static void main(String[]args){
MyThread thread =new MyThread();
thread.start();
thread.interrupt();
}
}
Thread end
3.Executor 的中断操作
调用Executor的shutdown()方法会等待线程都执行完之后再关闭,但是如果调的是shutdownNow()方法,就相当于调用每个线程的interrupt()方法。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.*;
public class ExecutorInterrupted{
public static void main(String[]args){
ExecutorService executorService=Executors.newCachedThreadPool();
executorService.execute(new MyRunnable());
executorService.shutdownNow();
System.out.println("Main run");
}
}
class MyRunnable implements Runnable{
public void run(){
try {
Thread.sleep(2000);
System.out.println("Thread run");
} catch (Exception e) {
e.printStackTrace(); //TODO: handle exception
}
}
}
Main run
pool-1-thread-1正在执行
java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at MyRunnable.run(MakeThreadPoll.java:32)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
如果只想中断Executor中的一个线程,可以通过使用submit()方法来提交一个线程,他会返回Future<?>对象。通过调用该对象的cancel(true)方法就可以中断线程。
Future<?>future=executorService.submit(()->{
//..
});
future.cancel(true)