线程状态及各状态下与锁和CPU的关系

Posted insanexs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程状态及各状态下与锁和CPU的关系相关的知识,希望对你有一定的参考价值。

线程的状态

Thread.State枚举类型中定义了线程的六种状态:NEWRUNNABLEBLOCKEDWAITINGTIMED_WAITINGTERMINATED

线程在某一时刻只能拥有一种状态,但是在线程的整个生命周期,线程的状态会发生变化。

public enum State {
        NEW,

        RUNNABLE,

        BLOCKED,

        WAITING,

        TIMED_WAITING,

        TERMINATED;
    }

各状态的说明

NEW

NEW状态是线程已经被创建,但还没调用start()。此时的线程是不可运行的,CPU将不会为其分配时间。

RUNNABLE

当新创建的线程调用了start(),线程便进入了RUNNABLE状态。
RUNNABLE状态是指可以获得CPU运行时间的状态,如果线程在此状态下,线程有两种子状态,一种是等待CPU时间,另一种是获得了CPU时间在执行代码。

BLOCKED

BLOCKED状态是线程无法获取对象锁时的状态。此状态下线程会阻塞,当线程成功获取到锁,线程将切换为RUNNABLE状态。
BLOCKED状态无法获得CPU运行时间。

WAITING

WAITING状态是指是指线程在执行过程中,主动出让自己CPU运行时间,让其他线程先执行,自己等待其它线程的特定操作后再恢复执行。

TIMED_WAITING

TIMED_WAITINGWAITING状态相似,TIMED_WAITING增加了时间限制,其实没有外部信号,在等待时间超时后,线程也会恢复。

TERMINATED

TERMINATED是线程的终止态,当线程执行完自己的任务,或在执行任务中发生了异常,线程都会进入TERMINATED,表示线程已经到了生命周期的末尾。

下图是关于线程间各状态切换的过程及发生状态切换的一些条件。
技术图片

操作 操作前线程状态 操作后线程状态 是否出让CPU时间 是否需要先持有对象锁 是否释放对象锁
new Thread() NEW
Thread.start() NEW RUNNABLE
synchronized能得到对象锁 RUNNABLE RUNNABLE
synchronized无法得到对象锁 RUNNABLE BLOCKED
Thread.join() RUNNABLE WAITING
Thread.join(t) RUNNABLE TIMED_WAITING
Thread.sleep(t) RUNNABLE TIMED_WAITING
Object.wait() RUNNABLE WAITING
Object.wait(t) RUNNABLE TIMED_WAITING
Object.notify() / Object.notifyAll() RUNNABLE RUNNABLE
Lock.lock() RUNNABLE WAITING
Lock.tryLock(t) RUNNABLE TIMED_WAITING
LockSupport.park() RUNNABLE WAITING
LockSupport.parkNanos(t)/LockSupport.parkUntil(t) RUNNABLE TIMED_WAITING
执行结束/执行异常 RUNNABLE TERMINATED

以下是一些测试代码,可以运行下清晰的了解到状态。
各状态切换测试:

public class ThreadStateTest {

    public static void main(String[] args){
        threadStateNew();

        workingThread();

        threadStateTerminate();

        threadBlockedByLock();

        threadBlockedBySynchronized();

        threadSleep();

        threadWait();

        threadTimedWait();
    }

    private static void threadStateNew(){
        System.out.println("--------------------------");
        System.out.print("Never Start Thread State:");
        Thread thread = new Thread(()->{

        }, "Thread Never Start");
        //print NEW
        System.out.println(thread.getState());
        System.out.println("--------------------------");
    }

    private static void workingThread(){
        System.out.println("--------------------------");
        Thread thread = new Thread(()->{
           for(int i=0; i<100; i++){
               doSomeElse();
           }
        });

        thread.start();

        doSomeElse();
        //print RUNNABLE
        System.out.println("Working Thread State:" + thread.getState());
        System.out.println("--------------------------");
    }

    private static void threadStateTerminate(){
        System.out.println("--------------------------");
        System.out.print("Finish Job Thread State:");
        Thread thread = new Thread(()->{

        }, "Thread Finish Job");
        thread.start();


        try {
            //Main Thread Will Wait util this thread finished job
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //print TERMINATED
        System.out.println(thread.getState());
        System.out.println("--------------------------");
    }

    private static void threadBlockedByLock(){
        System.out.println("--------------------------");
        System.out.print("Thread State Blocked By Lock:");
        ReentrantLock lock = new ReentrantLock();
        Thread thread = new Thread(()->{
                lock.lock();
        }, "Blocked Thread");

        lock.lock();

        thread.start();

        doSomeElse();
        //print WAITING
        System.out.println(thread.getState());

        lock.unlock();
        System.out.println("--------------------------");
    }

    private static void threadBlockedBySynchronized(){
        System.out.println("--------------------------");
        System.out.print("Thread Blocked By Synchronized:");
        Thread thread = new Thread(()->{
            synchronized (ThreadStateTest.class){

            }
        }, "Blocked by Synchronized Thread");

        synchronized (ThreadStateTest.class){
            thread.start();
            doSomeElse();
            //print BLOCKED
            System.out.println(thread.getState());
        }
        System.out.println("--------------------------");
    }

    private static void threadSleep(){
        System.out.println("--------------------------");
        System.out.print("Sleeping Thread:");
        Thread thread = new Thread(()->{
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "Thread sleep");

        thread.start();
        doSomeElse();
        //print TIMED_WAITING
        System.out.println(thread.getState());
        System.out.println("--------------------------");
    }


    private static void threadWait(){
        System.out.println("--------------------------");
        System.out.print("Thread Waiting:");
        Object lock = new Object();
        Thread threadA = new Thread(()->{
            synchronized (lock){
                try {
                    lock.wait();

                    for(int i=0; i<100; i++){
                        doSomeElse();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }, "Thread Waiting");

        Thread threadB = new Thread(()->{
            synchronized (lock){
                //print WAITING
                System.out.println("Before Notify, Thread A State:" + threadA.getState());
                lock.notify();
                //print BLOCKED
                System.out.println("After Notify, Thread A State:" + threadA.getState());
            }
        });


        threadA.start();
        doSomeElse();
        threadB.start();

        try {
            threadB.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //print RUNNABLE
        System.out.println("After Thread B finish job, Thread A State:" + threadA.getState());
        System.out.println("--------------------------");
    }

    private static void threadTimedWait(){
        System.out.println("--------------------------");
        System.out.print("Thread Waiting:");
        Object lock = new Object();
        Thread threadA = new Thread(()->{
            synchronized (lock){
                try {
                    lock.wait(1000);

                    for(int i=0; i<100; i++){
                        doSomeElse();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }, "Thread Waiting");

        Thread threadB = new Thread(()->{
            synchronized (lock){
                //print TIMED_WAITING
                System.out.println("Before Notify, Thread A State:" + threadA.getState());
                lock.notify();
                //print BLOCKED
                System.out.println("After Notify, Thread A State:" + threadA.getState());
            }
        });


        threadA.start();
        doSomeElse();
        threadB.start();

        try {
            threadB.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //print RUNNABLE
        System.out.println("After Thread B finish job, Thread A State:" + threadA.getState());
        System.out.println("--------------------------");
    }
    /**
     * take some times, let the thread get cpu time
     */
    private static void doSomeElse(){
        double meanless = 0d;
        for(int i=0; i<10000; i++){
            meanless += Math.random();
        }
    }

}

CPU时间运行测试:

public class ThreadCPUTimeTest {

    public static void main(String[] args) {
        testBlockedThreadCPUTime();
    }

    protected static void testBlockedThreadCPUTime() {
        Object lock = new Object();

        Thread threadA = new Thread(() -> {
            synchronized (lock) {
                doSomethingElse();
            }
        }, "ThreadA: Blocked because of synchronized");

        Thread threadB = new Thread(() -> {
            synchronized (lock) {
                try {
                    threadA.start();
                    Thread.sleep(100000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "ThreadB: With Monitor But Sleep");

        threadB.start();
        //Main Thread Executing Job
        for (int i = 0; i < 100000; i++) {
            doSomethingElse();
        }
    }

    private static void doSomethingElse() {
        double meanless = 0d;

        for (int i = 0; i < 10000; i++) {
            meanless += Math.random();
        }
    }
}

用VISUALVM可以统计CPU时间:
技术图片

详细代码可以GitHub

以上是关于线程状态及各状态下与锁和CPU的关系的主要内容,如果未能解决你的问题,请参考以下文章

并发编程-线程与锁

互斥锁自旋锁读写锁和条件变量

互斥锁,自旋锁,原子操作原理和实现

javas的四种状态 无锁状态 偏向锁状态 轻量级锁状态 重量级锁状态

线程安全与锁优化

浅谈自旋锁和 JVM 对锁的优化