Java线程状态分析/线程状态转换图

注:以下代码讲解基于JDK1.8.0_144

一、线程状态分类
 

线程一共有六种状态,分别为NewRUNNABLEBLOCKEDWAITINGTIMED_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:

         *

             *   

  • {@link Object#wait() Object.wait} with no timeout
  •          *   

  • {@link #join() Thread.join} with no timeout
  •          *   

  • {@link LockSupport#park() LockSupport.park}
  •          *

         *

         *

A thread in the waiting state is waiting for another thread to

         * perform a particular action.

         *

         * For example, a thread that has called Object.wait()

         * on an object is waiting for another thread to call

         * Object.notify() or Object.notifyAll() on

         * that object. A thread that has called Thread.join()

         * 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:

         *

             *   

  • {@link #sleep Thread.sleep}
  •          *   

  • {@link Object#wait(long) Object.wait} with timeout
  •          *   

  • {@link #join(long) Thread.join} with timeout
  •          *   

  • {@link LockSupport#parkNanos LockSupport.parkNanos}
  •          *   

  • {@link LockSupport#parkUntil LockSupport.parkUntil}
  •          *

         */

        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代码看到的线程状态而已。

三、状态转换图

Java线程状态分析/线程状态转换图_第1张图片

 四、常见场景

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状态

模拟两个线程抢锁,当一个线程抢到锁之后进入sleepsleep状态下不会释放锁,所以另外一个线程被阻塞。从堆栈信息可以看到,lockedwaiting 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 NEWTERMINATED状态

测试创建线程,启动线程,线程运行完毕。处于这两个状态的线程在堆栈不会出现在堆栈信息里面。

测试代码:

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.

你可能感兴趣的:(Java)