中断
一个线程在执行完毕之后会自动结束,如果在运行过程中发生异常也会提前结束
一个线程可能处于以下四种状态之一:
- 新建
- 就绪
- 阻塞
- 死亡
一个任务进入阻塞状态可能有以下原因:
- 调用sleep()使任务进入休眠状态,这种情况下,任务在指定的时间内不会运行
- 调用wait()使线程挂起。直到线程得到了notify()和notifyAll()消息,线程才会进入就绪状态
- 任务在等待某个输入输出完成
- 任务视图在某个对象上调用其同步控制方法,但是对象锁不可用,因为另一个任务已经获取了这个锁
一些阻塞可以中断,但是一些阻塞不可中断。
InterruptedException:
通过调用一个线程的 interrupt() 来中断该线程,如果该线程处于阻塞、限期等待或者无限期等待状态,那么就会抛出 InterruptedException,从而提前结束该线程。但是不能中断 I/O 阻塞和 synchronized 锁阻塞。
/** * interrupted * */ public class InterruptedTest implements Runnable{ @Override public void run() { try { Thread.sleep(3000); System.out.println("the end"); } catch (InterruptedException e) {//由于主线程内调用了中断,这里抛异常,睡眠以下的语句不会执行 e.printStackTrace(); } } public static void main(String[] args) { Thread thread = new Thread(new InterruptedTest()); thread.start(); thread.interrupt();//调用中断 System.out.println("main end"); } }
interrupted:
如果一个线程的 run() 方法执行一个无限循环,并且没有执行 sleep() 等会抛出 InterruptedException 的操作,那么调用线程的 interrupt() 方法就无法使线程提前结束。
但是调用 interrupt() 方法会设置线程的中断标记,此时调用 interrupted() 方法会返回 true。因此可以在循环体中使用 interrupted() 方法来判断线程是否处于中断状态,从而提前结束线程。
/** * interrupted * */ public class interruptedTest2 implements Runnable{ @Override public void run() { while (!Thread.interrupted()){ } System.out.println("Thread end"); } public static void main(String[] args) { Thread thread = new Thread(new interruptedTest2()); thread.start(); thread.interrupt();//如果将该句注释掉,该进程就会一直卡在死循环中出不来 System.out.println("main end"); } }
Executor 的中断操作:
调用 Executor 的 shutdown() 方法会等待线程都执行完毕之后再关闭,但是如果调用的是 shutdownNow() 方法,则相当于调用每个线程的 interrupt() 方法。
/** * Executor Interrupted * */ public class ExecuutorTest implements Runnable{ @Override public void run() { try { Thread.sleep(3000); System.out.println("ExecutorTest"); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { exec.execute(new ExecuutorTest()); } exec.shutdownNow(); System.out.println("main end"); } }
如果只想中断 Executor 中的一个线程,可以通过使用 submit() 方法来提交一个线程,它会返回一个 Future<?> 对象,通过调用该对象的 cancel(true) 方法就可以中断线程。
共同学习共同进步,如果错误,欢迎指正