线程状态
新建状态
线程被创建时,会短暂的处于这种状态。处于这种状态的线程已经分配了必须的系统资源,有资格获得cpu时间了,等待调度器把它转变为可运行状态或阻塞状态;
就绪状态
在这种状态下,只要调度器把时间片分配给线程,就可以马上运行;
阻塞状态
线程因为某个条件未满足,阻止了它的运行;这种状态会被调度器忽略,直到条件满足时,转为就绪状态;
死亡状态
线程运行结束或被中断后的状态;该状态不能被调度,不会分配cpu时间;
线程进入阻塞状态的方式
- 调用sleep方法
- 调用wait方法
- 任务等待某个输入输出完成
- 调用其它同步控制方法,等待其它线程释放锁
线程中断
线程阻塞及中断
先看一段代码,如下:
package concurrency; import java.util.concurrent.*; import java.io.*; class SleepBlocked implements Runnable { public void run() { try { TimeUnit.SECONDS.sleep(100); } catch (InterruptedException e) { System.out.println("InterruptedException"); } System.out.println("Exiting SleepBlocked.run()"); } } class IOBlocked implements Runnable { private InputStream in; public IOBlocked(InputStream is) { in = is; } public void run() { try { System.out.println("Waiting for read():"); in.read(); } catch (IOException e) { if (Thread.currentThread().isInterrupted()) { System.out.println("Interrupted from blocked I/O"); } else { throw new RuntimeException(e); } } System.out.println("Exiting IOBlocked.run()"); } } class SynchronizedBlocked implements Runnable { public synchronized void f() { while (true) // Never releases lock Thread.yield(); } public SynchronizedBlocked() { new Thread() { public void run() { f(); // Lock acquired by this thread } }.start(); } public void run() { System.out.println("Trying to call f()"); f(); System.out.println("Exiting SynchronizedBlocked.run()"); } } public class Interrupting { private static ExecutorService exec = Executors.newCachedThreadPool(); static void test(Runnable r) throws InterruptedException { Future<?> f = exec.submit(r); TimeUnit.MILLISECONDS.sleep(100); System.out.println("Interrupting " + r.getClass().getName()); f.cancel(true); // Interrupts if running System.out.println("Interrupt sent to " + r.getClass().getName()); } public static void main(String[] args) throws Exception { test(new SleepBlocked()); test(new IOBlocked(System.in)); test(new SynchronizedBlocked()); TimeUnit.SECONDS.sleep(3); System.out.println("Aborting with System.exit(0)"); System.exit(0); // ... since last 2 interrupts failed } }
以上代码中,展示了三种进入阻塞状态的情景:调用sleep方法,等待io,等待其它线程释放锁;
以及尝试调用Future的cancel方法去中断阻塞的线程,从运行结果可以发现,只有sleep可以被中断,其它等待io和等待锁释放都不能被中断;这一点也可以从sleep方法会抛出InterruptedException异常看出来,其它两个不会抛出该异常;
那么对于io阻塞和互斥锁阻塞的线程如何中断?
中断io阻塞
方式一,调用shutdownNow关闭线程池,调用close方法关闭IO流资源;
方式二,使用nio
中断互斥锁阻塞
使用并发库中的ReentrantLock锁;
ps:如果是同一个线程的话,是可以调用在同一个对象中的其它synchronized方法;
检查中断
调用Thread.interrupted(),查看interrupt()是否调用过,并清除中断状态,避免中断被通知两次;