并发(3) -- 中断
2017-11-01 本文已影响8人
黑色偏幽默
线程状态
- 新建(new):线程创建时,它只会短暂的处于这种状态。此时它已经分配了必须的系统资源,并执行了初始化。此刻线程已经有资格获取 CPU 时间了,之后调度器将把这个线程转变为可运行或者阻塞。
- 可运行(Runnable):在这种状态下,只要调度器把时间片分配给线程,线程就可以运行。
- 阻塞(Blocked):线程能够运行,但有某个条件阻止其运行,调度器将忽略阻塞线程,不为其分配 CPU 时间。
- 死亡(Dead):处于终止状态,通常是从 run()方法放回,但线程还是可以被中断。
进入阻塞状态
- 通过调用 sleep() 使任务进入休眠状态,任务在指定时间内不会运行。
- 通过 wait() �使线程挂起,直到线程得到 notity() 和 notityAll()。
- 任务在等待某个输入/输出完成。
- 任务试图在某个对象上调用其同步方法,但锁不可用。
中断
Thread.interrupt()
方法可以终止被阻塞的线程,这个方法将设置中断状态。
如果一个线程已经被阻塞,或者试图执行一个阻塞操作,那么设置这个线程的中断状态,将会抛出 InterruptedException
,而在抛出该异常或调用 Thread.interrupted()
后,中断状态将被复位。
cancel()
我们实现一个 runnable,可以看到在 Sleep 时是可以被中断阻塞的,实际上,任何要求抛出 InterruptedException
的调用都能被中断,但由于同步锁和 I/O 的阻塞却无法被中断。
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<?> future = executorService.submit(() -> {
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("before return");
});
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
future.cancel(true);
executorService.shutdown();
}
before return
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at Main$1.run(Main.java:15)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
使用
lookInterruptibly()
方式获取锁造成的阻塞可以被中断。