在到处java线程栈的时候,会看到线程栈第一行最后都有一个状态说明,下面就说一下这几种状态是什么情况下出现的,理解java线程栈对于分析问题非常有帮助;
/**
* 一. waiting for monitor entry
*
* BLOCKED (on object monitor)
* 等待进入synchronized临界区
*
* 二. in Object.wait()
* 1. TIMED_WAITING (on object monitor)
* 执行了java.lang.Object.wait(timeout)(Native Method)方法
*
* 2. WAITING (on object monitor)
* 执行了java.lang.Object.wait(Native Method)方法
*
*
* 三. waiting on condition
*
* 1.TIMED_WAITING (sleeping)
* java.lang.Thread.sleep(Native Method)
*
* 2.TIMED_WAITING (parking)
* sun.misc.UNSAFE.park(false, nanos);
* java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
*
* 3.WAITING (parking)
* sun.misc.UNSAFE.park(false, 0L);
* java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
*
* 4. RUNNABLE 特殊情况
* 很多本地线程处于此状态
*
* 四. runnable
*
* 1.RUNNABLE
* 正在jvm内运行的线程
*
* 2.RUNNABLE 特殊情况
* 正在执行本地方法的线程,jvm获取不到其状态,可能是阻塞状态;
*
* @author zqz
*
*/下面相机
waiting on condition
这种状态三种子状态:
一、TIMED_WAITING (sleeping)
当调用了Thread.sleep()方法时会进入这种状态,线程栈如下:
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
需要注意的是,如果线程持有锁,则不会释放锁;
二、TIMED_WAITING (parking)
sun.misc.UNSAFE.park(false, nanos);
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
三、WAITING (parking)
sun.misc.UNSAFE.park(false, 0L);
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
有以下几种情况会进入WAITING(parking)状态
- LockSupport.park()
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
直接在我们应用中调用了LockSupport.park()方法,没有参数,将当前线程阻塞;
- LockSupport.park(Object)
调用该方法有以下三种场景
1)ReentrantLock.lock()方法
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000d62762c0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)
这里是调用了可重入锁的lock方法,可重入锁最终是调用了LockSuport.park(Object)方法将线程阻塞的,与无参的LockSupport.Park()方法的调用栈是不一样的;
2)RetreenLock.newCondition().await()
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000d6276400> (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)
调用了RetreenLock.newCondition().await()方法,最终调用的也是LockSupport.park(Object)方法;
3)在应用中直接调用Locksupport.park(Object)方法
调用栈参考上面两个,这里就不列出来了
上面三种是一样的,列出前两种的目的是为了让大家清楚,当调用栈像给出的那样时,我们调用了哪些java哪些内置的方法间接调用的LockeSupprot.park(Object)方法;
四、 runnable
特殊情况,这种状态不一致的情况也会出现,处于此状态的线程正在执行本地方法,应该算是jvm中的一个bug;
waiting for monitor entry
这种状态的线程只有一种子状态:BLOCKED (on object monitor)
java.lang.Thread.State: BLOCKED (on object monitor)
at com.zqz.test.threadstate.ThreadStateTest$Monitor_EntrySet.Monitor_EntrySet_run(ThreadStateTest.java:137)
- waiting to lock <0x00000000d6274fa0> (a java.lang.Boolean)
线程进入synchronized同步块之前,因为已经有其它线程进入同步块了,所以当先线程被阻塞在EntrySet队列中等待进入synchronized代码块;
in Object.wait()
这种状态的线程有两种子状态:
1. TIMED_WAITING (on object monitor)
执行了java.lang.Object.wait(timeout)(Native Method)方法,带有是时间
2. WAITING (on object monitor)
执行了java.lang.Object.wait(Native Method)方法
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d6274fa0> (a java.lang.Boolean)
at java.lang.Object.wait(Object.java:502)
at com.zqz.test.threadstate.ThreadStateTest$Monitor_WaitSet.Monitor_WaitSet_run(ThreadStateTest.java:157)
- locked <0x00000000d6274fa0> (a java.lang.Boolean)
处于这种状态的线程,线程栈首先会有一个locked动作,说明其应进入到了synchronized代码块,在代码快中由于某些条件不满足,无法继续执行,又做了Object.Wait()操作释放锁进入等待状态;
runnable
java.lang.Thread.State: RUNNABLE
java线程正在运行,需要注意的是这种线程如果在执行本地方法,而本地方法阻塞了线程,虽然线程处于阻塞状态,但是java线程获取不到本地方法执行的状态,这时仍然显示runnable;
- Thread.sleep()
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
线程执行了sleep方法,需要注意的是,如果线程持有锁,则不会释放锁;
锁与线程栈的关系
Synchronized锁
来看下0x00000007d616a0c8锁的执行过程:
一、线程WaitSet--locked--waiting on--in Object.wait()1 先运行:
"WaitSet--locked--waiting on--in Object.wait()1" prio=6 tid=0x000000000d9fb800 nid=0x2e3c in Object.wait() [0x000000000e76f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007d616a0c8> (a java.lang.Boolean)
at java.lang.Object.wait(Object.java:503)
at com.zqz.test.threadstate.ThreadStateTest$Monitor_WaitSet.Monitor_WaitSet_run(ThreadStateTest.java:1525)
- locked <0x00000007d616a0c8> (a java.lang.Boolean)
at com.zqz.test.threadstate.ThreadStateTest$Monitor_WaitSet.run(ThreadStateTest.java:1517)
Locked ownable synchronizers:
- None
这个线程:
1. 执行- locked <0x00000007d616a0c8> (a java.lang.Boolean) 持有了锁;
2. 执行- waiting on <0x00000007d616a0c8> (a java.lang.Boolean) 执行了Object.wait()释放了锁,并进入到wait 队列;
二、线程”locked--sleeping--wait on Condition1“开始执行:
"locked--sleeping--wait on Condition1" prio=6 tid=0x000000000d9fc000 nid=0x142c waiting on condition [0x000000000e8bf000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.zqz.test.threadstate.ThreadStateTest$LockedSleeping.LockedSleeping_run(ThreadStateTest.java:1565)
- locked <0x00000007d616a0d8> (a java.lang.Object)
- locked <0x00000007d616a0c8> (a java.lang.Boolean)
at com.zqz.test.threadstate.ThreadStateTest$LockedSleeping.run(ThreadStateTest.java:1547)
Locked ownable synchronizers:
- None
这个线程在上面线程释放锁后,它执行 - locked <0x00000007d616a0c8> (a java.lang.Boolean) 持有了锁;
三、线程“EntrySet--waiting to lock---Waiting for monitor entry2”开始执行
"EntrySet--waiting to lock---Waiting for monitor entry2" prio=6 tid=0x000000000da03000 nid=0x383c waiting for monitor entry [0x000000000ebcf000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.zqz.test.threadstate.ThreadStateTest$Monitor_EntrySet.Monitor_EntrySet_run(ThreadStateTest.java:1505)
- waiting to lock <0x00000007d616a0c8> (a java.lang.Boolean)
at com.zqz.test.threadstate.ThreadStateTest$Monitor_EntrySet.run(ThreadStateTest.java:1492)
Locked ownable synchronizers:
- None
这个线程执行后发现锁已经被别的线程持有了,所以执行- waiting to lock <0x00000007d616a0c8> (a java.lang.Boolean) 进入到monitor entry队列,等待竞争锁;
ReentrantLock
"RTlock has Lock1" prio=6 tid=0x000000000da2c800 nid=0x3830 waiting on condition [0x000000000ed0f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.zqz.test.threadstate.ThreadStateTest$RTlockLocked.run(ThreadStateTest.java:1445)
Locked ownable synchronizers:
- <0x00000007d616a378> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
Locked ownable synchronizers: 代表当前线程持有了0x00000007d616a378锁
"RTlock wait Lock2" prio=6 tid=0x000000000da34000 nid=0xacc waiting on condition [0x000000000ee9f000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007d616a378> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:834)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:867)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1197)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290)
at com.zqz.test.threadstate.ThreadStateTest$RTlockWaitLocke.run(ThreadStateTest.java:1470)
Locked ownable synchronizers:
- None
- parking to wait for <0x00000007d616a378> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
代表当前线程正在等待0x00000007d616a378锁
LockSupport.park()锁
"LockSupportPark2--park1" prio=6 tid=0x000000000d9f6800 nid=0x2a44 waiting on condition [0x000000000e66f000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007d616e988> (a com.zqz.test.threadstate.ThreadStateTest$LockSupportPark2)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at com.zqz.test.threadstate.ThreadStateTest$LockSupportPark2.park(ThreadStateTest.java:1610)
at com.zqz.test.threadstate.ThreadStateTest$LockSupportPark2.parkMethod(ThreadStateTest.java:1605)
at com.zqz.test.threadstate.ThreadStateTest$LockSupportPark2.run(ThreadStateTest.java:1602)
Locked ownable synchronizers:
- None
代表它执行LockSupport.park把自己给阻塞了,需要另外一个线程unpark这个线程才能继续执行;这种情况并没有其它线程持有锁