在到处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)状态
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()方法,没有参数,将当前线程阻塞;
调用该方法有以下三种场景
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)方法;
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;
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这个线程才能继续执行;这种情况并没有其它线程持有锁
在到处java线程栈的时候,会看到线程栈第一行最后都有一个状态说明,下面就说一下这几种状态是什么情况下出现的,理解java线程栈对于分析问题非常有帮助; /** * 一. waiting for monitor entry * * BLOCKED (on object monitor) * 等待进入synchronized临界区 * * 二. in Object.wai...
线
程
栈
(ThreadStack)和JVM
栈
(JVMStack)是相关的概念,它们在
Java
中扮演不同的角色。
1、
线
程
栈
(ThreadStack):
-每个
线
程在
Java
中都有自己的
线
程
栈
。
-
线
程
栈
用于存储
线
程执行过程中的方法调用和局部变量等信息。
-每当一个方法被调用时,
线
程
栈
会为该方法创建一个
栈
帧(StackFrame)并入
栈
。
-
栈
帧包含了方法的参数、局部变量以及方法的返回值等信息。
-当方法执行完成后,
栈
帧出
栈
,控制权返回到调用
"2019-04-12 18:21:24
Full thread dump
Java
HotSpot(TM) 64-Bit Server VM (25.20-b23 mixed mode):
\"Attach Listener\" #605 da...
1,
线
程
状态
为“waiting for monitor entry”:
意味着它在等待进入一个临界区,所以它在”Entry Set“队列中等待。
此时
线
程
状态
一般都是 Blocked:
java
.lang.Thread.State:BLOCKED(on object moni...
`newFixedThreadPool` 是
Java
中
线
程池的一种实现方式,它可以创建一个固定大小的
线
程池,并且只有在池中的所有
线
程都处于忙碌
状态
时,才会将新的任务加入到队列中等待执行。
以下是 `newFixedThreadPool` 的详细解释:
1. 创建一个固定大小的
线
程池,该
线
程池中的
线
程数量是固定的,一旦创建便无法更改。这意味着,如果池中的所有
线
程都处于忙碌
状态
并且有更多的任务需要执行,那么这些任务将会被放置在一个队列中,等待空闲
线
程的出现。
2.
线
程池中的所有
线
程都是可重用的,这意味着在执行完任务之后,
线
程将返回
线
程池并等待下一个任务的到来。
3.
线
程池中的所有
线
程都是后台
线
程,这意味着它们不会阻止应用程序的关闭。
4.
线
程池中的任务可以是任何实现了 `Runnable` 接口或 `Callable` 接口的对象。使用 `Callable` 接口可以允许任务返回一个值,并且可以抛出异常。
5.
线
程池中的任务将按照加入队列的顺序进行执行。
6. `newFixedThreadPool` 的底层实现是一个无界的工作队列和一个固定数量的
线
程池。
使用 `newFixedThreadPool` 可以有效地控制
线
程的数量,从而避免创建过多的
线
程而导致系统的资源浪费和性能下降。但是,如果任务的数量过多,而
线
程池中的
线
程数量过少,那么仍然会出现任务排队等待的情况。因此,在使用 `newFixedThreadPool` 时,需要根据实际情况来确定
线
程池的大小。