相关文章推荐
聪明伶俐的泡面  ·  Python ...·  1 年前    · 

在到处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)方法;

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这个线程才能继续执行;这种情况并没有其它线程持有锁 在到处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` 时,需要根据实际情况来确定 线 程池的大小。