1. Block
模拟代码:
1 /** 2 * 线程等待锁的情况 3 * 使用jstack 查看 4 * 哪个线程正在等待锁 5 * 线程正在等待哪个锁 6 * 等待的锁由哪个线程占有 7 */ 8 public class BlockDemo { 9 public static void main(String[] args) throws InterruptedException { 10 new Thread(new Runnable() { 11 @Override 12 public void run() { 13 try { 14 System.out.println("thread-0 sleep 1000ms"); 15 Thread.sleep(1000); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 } 19 synchronized ("123"){ 20 System.out.println("thread-0 run..."); 21 } 22 } 23 }).start(); 24 25 // main线程占有锁后睡眠 26 synchronized ("123"){ 27 System.out.println("main sleep..."); 28 Thread.sleep(50000); 29 } 30 System.out.println("main over"); 31 } 32 }
状态查看:
1 C:Userswqz>jps 2 11792 BlockDemo 3 12688 Launcher 4 9816 Jps 5 1548 6 7 C:Userswqz>jstack -l 11792 8 2020-03-21 16:57:57 9 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode): 10 11 "Thread-0" #11 prio=5 os_prio=0 tid=0x0000000018bab800 nid=0xbc8 waiting for monitor entry [0x00000000197ae000] 12 java.lang.Thread.State: BLOCKED (on object monitor) 13 at cn.wqz.jvm.stack.BlockDemo$1.run(BlockDemo.java:22) 14 - waiting to lock <0x00000000d5ecbb20> (a java.lang.String) 15 at java.lang.Thread.run(Thread.java:748) 16 17 Locked ownable synchronizers: 18 - None 19 20 ...
21 "main" #1 prio=5 os_prio=0 tid=0x0000000002b02800 nid=0x4018 waiting on condition [0x000000000256f000] 22 java.lang.Thread.State: TIMED_WAITING (sleeping) 23 at java.lang.Thread.sleep(Native Method) 24 at cn.wqz.jvm.stack.BlockDemo.main(BlockDemo.java:30) 25 - locked <0x00000000d5ecbb20> (a java.lang.String) 26 27 Locked ownable synchronizers: 28 - None
2. in object.wait()
模拟代码:
1 /** 2 * 线程wait情况 3 */ 4 public class ObjectWaitDemo { 5 public static void main(String[] args) throws InterruptedException { 6 new Thread(new Runnable() { 7 @Override 8 public void run() { 9 System.out.println("thread-0 sleep..."); 10 try { 11 Thread.sleep(10000); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 synchronized ("123"){ 16 System.out.println("thread-0 run"); 17 try { 18 Thread.sleep(5000); 19 } catch (InterruptedException e) { 20 e.printStackTrace(); 21 } 22 System.out.println("thread-0 notify"); 23 "123".notify(); 24 } 25 } 26 }).start(); 27 28 synchronized ("123"){ 29 System.out.println("main before wait"); 30 "123".wait(); // 不唤则不醒 31 System.out.println("main after wait"); 32 } 33 } 34 }
状态查看:
1 C:Userswqz>jstack -l 2620 2 2020-03-21 17:11:23 3 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode): 4 5 "Thread-0" #11 prio=5 os_prio=0 tid=0x0000000018b29000 nid=0x426c waiting on condition [0x000000001973f000] 6 java.lang.Thread.State: TIMED_WAITING (sleeping) 7 at java.lang.Thread.sleep(Native Method) 8 at cn.wqz.jvm.stack.ObjectWaitDemo$1.run(ObjectWaitDemo.java:20) 9 - locked <0x00000000d5ecc238> (a java.lang.String) 10 at java.lang.Thread.run(Thread.java:748) 11 12 Locked ownable synchronizers: 13 - None 14 15 . . . 16 17 "main" #1 prio=5 os_prio=0 tid=0x0000000002a92800 nid=0x3c28 in Object.wait() [0x0000000000c6f000] 18 java.lang.Thread.State: WAITING (on object monitor) 19 at java.lang.Object.wait(Native Method) 20 - waiting on <0x00000000d5ecc238> (a java.lang.String) 21 at java.lang.Object.wait(Object.java:502) 22 at cn.wqz.jvm.stack.ObjectWaitDemo.main(ObjectWaitDemo.java:31) 23 - locked <0x00000000d5ecc238> (a java.lang.String) 24 25 Locked ownable synchronizers: 26 - None
注意: wait中的线程,不被唤醒的话不会醒来
3. waiting on condition
模拟代码:
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; /** * 创建阻塞条件 * waiting on condition */ public class WaitingOnConditionDemo { public static void main(String[] args) { BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(1); blockingQueue.add("123"); try { //阻塞的添加 blockingQueue.put("123"); } catch (InterruptedException e) { e.printStackTrace(); } } }
状态查看:
1 "main" #1 prio=5 os_prio=0 tid=0x0000000002c82800 nid=0x40f8 waiting on condition [0x000000000279f000] 2 java.lang.Thread.State: WAITING (parking) 3 at sun.misc.Unsafe.park(Native Method) 4 - parking to wait for <0x00000000d6021678> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) 5 at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 6 at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) 7 at java.util.concurrent.ArrayBlockingQueue.put(ArrayBlockingQueue.java:353) 8 at cn.wqz.jvm.stack.WaitingOnConditionDemo.main(WaitingOnConditionDemo.java:13) 9 10 Locked ownable synchronizers: 11 - None
4. 总结
状态说明:
- New: 当线程对象创建时存在的状态,此时线程不可能执行;
- Runnable:当调用thread.start()后,线程变成为Runnable状态。只要得到CPU,就可以执行;
- Running:线程正在执行;
- Waiting:执行thread.join()或在锁对象调用obj.wait()等情况就会进该状态,表明线程正处于等待某个资源或条件发生来唤醒自己;
- Timed_Waiting:执行Thread.sleep(long)、thread.join(long)或obj.wait(long)等就会进该状态,与Waiting的区别在于Timed_Waiting的等待有时间限制;
- Blocked:如果进入同步方法或同步代码块,没有获取到锁,则会进入该状态;
- Dead:线程执行完毕,或者抛出了未捕获的异常之后,会进入dead状态,表示该线程结束
- 其次,对于jstack日志,我们要着重关注如下关键信息
- Deadlock:表示有死锁
- Waiting on condition:等待某个资源或条件发生来唤醒自己。具体需要结合jstacktrace来分析,比如线程正在sleep,网络读写繁忙而等待
- Blocked:阻塞
- Waiting on monitor entry:在等待获取锁
- in Object.wait():获取锁后又执行obj.wait()放弃锁
- 对于Waiting on monitor entry 和 in Object.wait()的详细描述:Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。从下图中可以看出,每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 "Active Thread",而其它线程都是 "Waiting Thread",分别在两个队列 " Entry Set"和 "Wait Set"里面等候。在 "Entry Set"中等待的线程状态是 "Waiting for monitor entry",而在 "Wait Set"中等待的线程状态是 "in Object.wait()"
经验:
如果说系统慢,那么要特别关注Blocked,Waiting on condition
如果说系统的cpu耗的高,那么肯定是线程执行有死循环,那么此时要关注下Runable状态。
本文结束。