捞逼205文集。

并发(3) -- 中断

2017-11-01  本文已影响8人  黑色偏幽默

线程状态

  1. 新建(new):线程创建时,它只会短暂的处于这种状态。此时它已经分配了必须的系统资源,并执行了初始化。此刻线程已经有资格获取 CPU 时间了,之后调度器将把这个线程转变为可运行或者阻塞。
  2. 可运行(Runnable):在这种状态下,只要调度器把时间片分配给线程,线程就可以运行。
  3. 阻塞(Blocked):线程能够运行,但有某个条件阻止其运行,调度器将忽略阻塞线程,不为其分配 CPU 时间。
  4. 死亡(Dead):处于终止状态,通常是从 run()方法放回,但线程还是可以被中断。

进入阻塞状态

  1. 通过调用 sleep() 使任务进入休眠状态,任务在指定时间内不会运行。
  2. 通过 wait() �使线程挂起,直到线程得到 notity() 和 notityAll()。
  3. 任务在等待某个输入/输出完成。
  4. 任务试图在某个对象上调用其同步方法,但锁不可用。

中断

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() 方式获取锁造成的阻塞可以被中断。

上一篇 下一篇

猜你喜欢

热点阅读