注:以下代码讲解基于JDK1.8.0_144
一、线程状态分类
线程一共有六种状态,分别为New、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING
TERMINATED,同一时刻只有一种状态,通过线程的getState方法可以获取线程的状态。
二、线程状态讲解
2.1 NEW
/**
* Thread state for a thread which has not yet started.
*/
NEW,
当线程被创建出来还没有被调用start()时候的状态。
2.2 RUNNABLE
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
当线程被调用了start(),且处于等待操作系统分配资源(如CPU)、等待IO连接、正在运行状态,即表示Running状态和Ready状态。
注:不一定被调用了start()立刻会改变状态,还有一些准备工作,这个时候的状态是不确定的。
2.3 BLOCKED
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
等待监视锁,这个时候线程被操作系统挂起。当进入synchronized块/方法或者在调用wait()被唤醒/超时之后重新进入synchronized块/方法,锁被其它线程占有,这个时候被操作系统挂起,状态为阻塞状态。
阻塞状态的线程,即使调用interrupt()方法也不会改变其状态。
2.4 WAITING
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
无条件等待,当线程调用wait()/join()/LockSupport.park()不加超时时间的方法之后所处的状态,如果没有被唤醒或等待的线程没有结束,那么将一直等待,当前状态的线程不会被分配CPU资源和持有锁。
2.5 TIMED_WAITING
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
有条件的等待,当线程调用sleep(睡眠时间)/wait(等待时间)/join(等待时间)/ LockSupport.parkNanos(等待时间)/LockSupport.parkUntil(等待时间)方法之后所处的状态,在指定的时间没有被唤醒或者等待线程没有结束,会被系统自动唤醒,正常退出。
2.6 TERMINATED
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
执行完了run()方法。其实这只是Java语言级别的一种状态,在操作系统内部可能已经注销了相应的线程,或者将它复用给其他需要使用线程的请求,而在Java语言级别只是通过Java代码看到的线程状态而已。
三、状态转换图
四、常见场景
4.1 RUNNABLE状态
主要是测试在进入run方法之后线程的状态,以及在等待IO的时候,线程的状态。
测试代码:
public static void testStateRunnable() { IOThread simpleThread = new IOThread("IOThread"); simpleThread.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Main thread check the state is " + simpleThread.getState() + "."); // RUNNABLE } static class IOThread extends Thread { public IOThread(String name) { super(name); } @Override public void run() { System.out.println("In run method, state is " + getState() + "."); // RUNNABLE Socket socket = new Socket(); try { System.out.println("Try to connect socket address which not exist..."); socket.connect(new InetSocketAddress( InetAddress.getByAddress(new byte[] { (byte) 192, (byte) 168, 1, 14 }), 5678)); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
测试结果:
In run method, state is RUNNABLE. Try to connect socket address which not exist... Main thread check the state is RUNNABLE.
堆栈信息:
"IOThread" #10 prio=5 os_prio=0 tid=0x00000000187c7800 nid=0x8b0 runnable [0x00000000192ee000] java.lang.Thread.State: RUNNABLE at java.net.DualStackPlainSocketImpl.connect0(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) - locked <0x00000000eb6c0fa8> (a java.net.DualStackPlainSocketImpl) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at java.net.Socket.connect(Socket.java:538) at com.test.threadpool.TestThreadState$IOThread.run(TestThreadState.java:83)
4.2 BLOCKED状态
模拟两个线程抢锁,当一个线程抢到锁之后进入sleep,sleep状态下不会释放锁,所以另外一个线程被阻塞。从堆栈信息可以看到,locked和waiting to lock都是同一个对象。
测试代码:
public static void testBlockedState() { Object lock = new Object(); SleepThread t1 = new SleepThread("t1", lock); SleepThread t2 = new SleepThread("t2", lock); t1.start(); t2.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread t1's state " + t1.getState()); System.out.println("Thread t2's state " + t2.getState()); } static class SleepThread extends Thread { private String name; private Object lock; public SleepThread(String name, Object lock) { super(name); this.name = name; this.lock = lock; } @Override public void run() { System.out.println("Thread:" + name + " in run."); synchronized (lock) { System.out.println("Thread:" + name + " hold the lock."); try { Thread.sleep(1000 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread:" + name + " return the lock."); } } }
测试结果:
Thread:t2 in run. Thread:t1 in run. Thread:t2 hold the lock. Thread t1's state BLOCKED Thread t2's state TIMED_WAITING
堆栈信息:
"t2" #11 prio=5 os_prio=0 tid=0x0000000018604800 nid=0x934 waiting on condition [0x000000001920f000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at com.test.threadpool.TestThreadState$SleepThread.run(TestThreadState.java:274) - locked <0x00000000eb64b910> (a java.lang.Object) "t1" #10 prio=5 os_prio=0 tid=0x000000001860b000 nid=0x3528 waiting for monitor entry [0x000000001910f000] java.lang.Thread.State: BLOCKED (on object monitor) at com.test.threadpool.TestThreadState$SleepThread.run(TestThreadState.java:271) - waiting to lock <0x00000000eb64b910> (a java.lang.Object)
4.3 WAITING状态
4.3.1 调用wait()方法导致的WAITING状态。
测试代码:
/** * 线程调用wait方法,状态变成WAITING。 */ public static void testStateWatingByWait() { Object lock = new Object(); WaitingThread waitingThread = new WaitingThread("WaitingThread", lock); waitingThread.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Main thread check the state is " + waitingThread.getState() + "."); // WAITING } static class WaitingThread extends Thread { private int timeout = 0; private Object lock; public WaitingThread(String name, Object lock) { this(name, lock, 0); } public WaitingThread(String name, Object lock, int timeout) { super(name); this.timeout = timeout; this.lock = lock; } @Override public void run() { synchronized (lock) { if (timeout == 0) { try { System.out.println("Try to wait."); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { try { System.out.println("Try to wait in " + timeout + "."); lock.wait(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println("Over thread."); } }
测试结果:
Try to wait. Main thread check the state is WAITING.
堆栈信息:
"WaitingThread" #10 prio=5 os_prio=0 tid=0x0000000018dea000 nid=0x1220 in Object.wait() [0x00000000198ee000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000eb6477e8> (a java.lang.Object) at java.lang.Object.wait(Object.java:502) at com.test.threadpool.TestThreadState$WaitingThread.run(TestThreadState.java:138) - locked <0x00000000eb6477e8> (a java.lang.Object)
4.3.2 调用join()方法导致的WAITING状态。
thread.join()方法其实就是synchronized(thread)内部一直判断thread的状态,如果为存活状态,就wait一个指定的时间,默认为0,然后继续循环判断,直到状态不为存活状态。
测试代码:
/** * 线程调用join方法,状态变成WAITING。 */ public static void testStateWatingByJoin() { Object lock = new Object(); WaitingThread waitingThread = new WaitingThread("WaitingThread", lock); waitingThread.start(); JoinThread joinThread = new JoinThread("JoinThread", waitingThread); joinThread.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Main thread check the join thread's state is " + joinThread.getState() + "."); // WAITING } static class JoinThread extends Thread { private int timeout = 0; private Thread thread; public JoinThread(String name, Thread thread) { this(name, thread, 0); } public JoinThread(String name, Thread thread, int timeout) { super(name); this.timeout = timeout; this.thread = thread; } @Override public void run() { if (timeout == 0) { try { System.out.println("Try to join."); thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } else { try { System.out.println("Try to join in " + timeout + "."); thread.join(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Over join."); } } static class WaitingThread extends Thread { private int timeout = 0; private Object lock; public WaitingThread(String name, Object lock) { this(name, lock, 0); } public WaitingThread(String name, Object lock, int timeout) { super(name); this.timeout = timeout; this.lock = lock; } @Override public void run() { synchronized (lock) { if (timeout == 0) { try { System.out.println("Try to wait."); lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { try { System.out.println("Try to wait in " + timeout + "."); lock.wait(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println("Over thread."); } }
测试结果:
Try to wait. Try to join. Main thread check the state is WAITING.
堆栈信息:
"JoinThread" #11 prio=5 os_prio=0 tid=0x0000000019007000 nid=0x33c0 in Object.wait() [0x0000000019c1f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000eb64a498> (a com.test.threadpool.TestThreadState$WaitingThread) at java.lang.Thread.join(Thread.java:1252) - locked <0x00000000eb64a498> (a com.test.threadpool.TestThreadState$WaitingThread) at java.lang.Thread.join(Thread.java:1326) at com.test.threadpool.TestThreadState$JoinThread.run(TestThreadState.java:194) "WaitingThread" #10 prio=5 os_prio=0 tid=0x0000000019006000 nid=0x35ac in Object.wait() [0x0000000019b1f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000eb64a468> (a java.lang.Object) at java.lang.Object.wait(Object.java:502) at com.test.threadpool.TestThreadState$WaitingThread.run(TestThreadState.java:138) - locked <0x00000000eb64a468> (a java.lang.Object)
4.3.3 调用LockSupport.park方法导致的WAITING状态。
使用线程池的时候经常会遇到这种状态,当线程池里面的任务都执行完毕,会等待获取任务。
测试代码:
public static void testStateWatingByThreadExecutor() { ExecutorService executeService = Executors.newSingleThreadExecutor(); executeService.submit(new Runnable() { @Override public void run() { System.out.println("Over Run."); } }); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } }
堆栈信息:
"pool-1-thread-1" #10 prio=5 os_prio=0 tid=0x0000000018f9c000 nid=0x2e88 waiting on condition [0x0000000019aaf000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000000eb64cc30> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
4.4 TIMED_WAITING状态
只测试sleep()方法,其余参照WAITING状态。
测试代码:
public static void testSleep() { try { Thread.sleep(1000 * 100); } catch (InterruptedException e) { e.printStackTrace(); } }
堆栈信息:
"main" #1 prio=5 os_prio=0 tid=0x0000000004f80800 nid=0x34bc waiting on condition [0x0000000004e7f000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at com.test.threadpool.TestThreadState.testSleep(TestThreadState.java:233) at com.test.threadpool.TestThreadState.main(TestThreadState.java:53)
4.5 NEW和TERMINATED状态
测试创建线程,启动线程,线程运行完毕。处于这两个状态的线程在堆栈不会出现在堆栈信息里面。
测试代码:
public static void testNewAndTerminatedState() { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("Over Run."); } }); System.out.println("State " + thread.getState() + "."); thread.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("State " + thread.getState() + "."); }
测试结果:
State NEW. Over Run. State TERMINATED.