线程一共有六种状态,分别为New、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING
TERMINATED,同一时刻只有一种状态,通过线程的getState方法可以获取线程的状态。
/**
* Thread state for a thread which has not yet started.
*/
NEW,
当线程被创建出来还没有被调用start()时候的状态。
/**
* 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()立刻会改变状态,还有一些准备工作,这个时候的状态是不确定的。
/**
* 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()方法也不会改变其状态。
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
*
*
*
*
*
*
*
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资源和持有锁。
/**
* 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:
*
*
*
*
*
*
*
*/
TIMED_WAITING,
有条件的等待,当线程调用sleep(睡眠时间)/wait(等待时间)/join(等待时间)/ LockSupport.parkNanos(等待时间)/LockSupport.parkUntil(等待时间)方法之后所处的状态,在指定的时间没有被唤醒或者等待线程没有结束,会被系统自动唤醒,正常退出。
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
执行完了run()方法。其实这只是Java语言级别的一种状态,在操作系统内部可能已经注销了相应的线程,或者将它复用给其他需要使用线程的请求,而在Java语言级别只是通过Java代码看到的线程状态而已。
主要是测试在进入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)
模拟两个线程抢锁,当一个线程抢到锁之后进入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)
测试代码:
/**
* 线程调用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)
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)
使用线程池的时候经常会遇到这种状态,当线程池里面的任务都执行完毕,会等待获取任务。
测试代码:
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)
只测试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)
测试创建线程,启动线程,线程运行完毕。处于这两个状态的线程在堆栈不会出现在堆栈信息里面。
测试代码:
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.