聊聊Java线程状态和常见误区

一、Java Thread文档

关于Java的线程状态,Java Thread文档讲的非常的清楚了,如果英文水平有4级的话,建议直接阅读文档。

二、Java线程状态

java的线程一共有6个状态:NewRunnableWaitingTimed_WaitingBlockedTerminate
这里Java使用Thread类的内部枚举类进行表示,简要信息如下:

public enum State { 
        NEW,

        RUNNABLE,

        BLOCKED,

        WAITING,

        TIMED_WAITING,

        TERMINATED;
}

需要注意的是,Java的线程状态线程在JVM上的状态,和操作系统的线程状态无关。也就是说,当一个Java线程处于Blocked状态时,并不代表它在操作系统层面的状态是Blocked,只能说明它在JVM层面的状态是Blocked。这一点在文档上有说明:

These states are virtual machine states which do not reflect any operating system thread states.
这些状态仅仅表示VM(虚拟机)的状态,并不代表操作系统的线程状态。

三、Java线程状态详解

  1. New:当一个线程刚刚被创建(new),但是还未被启动(调用start()方法),这个线程就处于New状态;
  2. Runnable:一个线程处于可以被调用的状态时,就是Runnable状态;
  3. Blocked:一个线程要进入synchronized同步代码块,但相关锁被其它线程占有时,线程就会进入Blocked。当线程notify()方法或者notifyAll()方法唤醒时,线程也会进入Blocked状态;
  4. Waiting:线程调用Object#wait()Thread.join()LockSupport.park()方法时,就会进入Waiting状态;
  5. Time_Waiting:线程调用Thread.sleep()Object#wiat(long timeout)Thread.join(long timeout)LockSupport.parkNanos()LockSupport.parkUntil()时,就会进入Time_Waiting状态;
  6. Terminate:代表线程已经终止。

四、Java线程状态转换

上一张我在网上找的图:
Java线程各个状态之间的转换
说说几个值得注意的点:

  1. 调用notify()notifyAll()方法并不会将线程状态从WaitingTimed_Waiting转换为Runnable,而是将线程状态转换为Blocked
  2. 图中并没有画出LockSupport.unpark()会将线程的线程线程状态转换,我在网上也没有找到相关的资料,个人认为LockSupport.unpark()会将线程状态从Waiting或者Timed_Waiting转换为Runnable
  3. 那如果我调用了Lock#lock(),线程获取锁失败,线程会进入Blocked还是Waiting状态?线程调用Lock#lock,其实本质是调用了LockSupport.park(),我们可以写一个简单的程序验证一下:
public class ThreadState {
    private static final ReentrantLock LOCK = new ReentrantLock();

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(new MyThread(), "Thread-" + i).start();
        }
        loop();
    }

    private static class MyThread implements Runnable {
        @Override
        public void run() {
            LOCK.lock();
            loop();
        }
    }

    private static void loop() {
        for (; ; ) {
            // do nothing
        }
    }
}

运行程序后,使用VisualVM将线程状态Dump下来,部分如下:

"Thread-0" #13 prio=5 os_prio=0 cpu=19062.50ms elapsed=19.85s tid=0x0000015e40a21000 nid=0x2730c runnable  [0x0000000d701fe000]
   java.lang.Thread.State: RUNNABLE
	at thread.ThreadState.loop(ThreadState.java:29)
	at thread.ThreadState$Thread.run(ThreadState.java:24)
	at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

   Locked ownable synchronizers:
	- <0x0000000089b4f998> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"Thread-1" #14 prio=5 os_prio=0 cpu=0.00ms elapsed=19.85s tid=0x0000015e40a22000 nid=0x269c4 waiting on condition  [0x0000000d702ff000]
   java.lang.Thread.State: WAITING (parking)
	at jdk.internal.misc.Unsafe.park(java.base@11.0.2/Native Method)
	- parking to wait for  <0x0000000089b4f998> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
	at java.util.concurrent.locks.LockSupport.park(java.base@11.0.2/LockSupport.java:194)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(java.base@11.0.2/AbstractQueuedSynchronizer.java:885)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(java.base@11.0.2/AbstractQueuedSynchronizer.java:917)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@11.0.2/AbstractQueuedSynchronizer.java:1240)
	at java.util.concurrent.locks.ReentrantLock.lock(java.base@11.0.2/ReentrantLock.java:267)
	at thread.ThreadState$Thread.run(ThreadState.java:23)
	at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

   Locked ownable synchronizers:
	- None

"Thread-2" #15 prio=5 os_prio=0 cpu=0.00ms elapsed=19.85s tid=0x0000015e40a2b000 nid=0x24170 waiting on condition  [0x0000000d703ff000]
   java.lang.Thread.State: WAITING (parking)
	at jdk.internal.misc.Unsafe.park(java.base@11.0.2/Native Method)
	- parking to wait for  <0x0000000089b4f998> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
	at java.util.concurrent.locks.LockSupport.park(java.base@11.0.2/LockSupport.java:194)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(java.base@11.0.2/AbstractQueuedSynchronizer.java:885)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(java.base@11.0.2/AbstractQueuedSynchronizer.java:917)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@11.0.2/AbstractQueuedSynchronizer.java:1240)
	at java.util.concurrent.locks.ReentrantLock.lock(java.base@11.0.2/ReentrantLock.java:267)
	at thread.ThreadState$Thread.run(ThreadState.java:23)
	at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

   Locked ownable synchronizers:
	- None

可以看出,Thread-1和Thread-2由于调用了LockSupport.park()都处于Waiting状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值