线程状态

线程状态在windows,linux和android等OS中状态都是不一致的,Java对线程状态做了一个抽象。

在java中线程状态由Thread内部内State表示

java.lang.Thread.State

These states are virtual machine states which do not reflect any operating system thread states.

这些线程状态不等于任何操作系统的线程状态

线程状态有,NEW,RUNABLE,WATING,TIMED_WAITING,TERMINATED

NEW

A thread that has not yet started is in this state.

一个线程被new出来后,并没有开始执行。

RUNNABLE

A thread executing in the Java virtual machine is in this state.

一个线程在JVM进程中运行的状态。

BLOCKED

A thread that is blocked waiting for a monitor lock is in this state.

一个线程在等待monitor lock 进入的状态。

WAITING

A thread that is waiting indefinitely for another thread to perform a particular action is in this state.

无限等待其他线程执行的状态。

TIMED_WAITING

A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.

有限时间内等待其他线程执行的状态

TERMINATED

A thread that has exited is in this state.

线程已经退出的状态。

Java线程状态实例

RUNNABLE

public static void runnable() {
        Thread thread = new Thread(() -> {
            while (true) {
            }
        }, "Runnable 状态的线程");
        thread.start();
    }

控制台监控的状态,简史和管理控制台通过(jconsole 监控工具查看,和之前提到的jvisualvm类似,jvisualvm后出来,也可以用jstack <pid>查看,jstack是命令行工具,三个监控工具,结果是一致的。)

java thread cpu 确认 java thread state_线程状态

BLOCKED

阻塞状态实例,等待synchronized(class字节码层面的monitorenter)进入的状态。

public static void blocked() throws InterruptedException {
        final Object object = new Object();
        Thread runnableThread = new Thread(() -> {
            synchronized (object) {
                while (true) {

                }
            }
        }, "Runnable 状态的线程");

        Thread blockedThread = new Thread(() -> {
            synchronized (object) {

            }
        }, "blocked 状态的线程。");

        runnableThread.start();
        //等待runnable 线程已经启动后再启动blockedThread
        Thread.sleep(500);
        blockedThread.start();
    }

控制台结果

java thread cpu 确认 java thread state_并发编程_02

WAITING

waiting状态,在三种情况下可以出现,Object.wait,Thread.join,LockSupport.park

object.wait实例

这里在object上调用wait()方法的前提是必须要synchronized()获取锁后,不然会抛错,与之相对的释放状态就是object.notify()(随机唤醒在object上监听的一个线程,让它获取object的锁)或object.notifyAll()(通知所有监听在object对象上的线程,让他们同时竞争,只有一个可以获取object上的锁),由于没法唤醒指定的线程获取object的锁,所以,在java1.5就出现了Lock和Condition,后面会详细讲Lock。

private static void waiting() throws InterruptedException {
        final Object object = new Object();
        Thread waitingThread = new Thread(() -> {
            synchronized (object) {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }, "waiting 状态的线程");
        waitingThread.start();
    }

监控情况

java thread cpu 确认 java thread state_并发编程_03

  thread.join实例

private static void join() throws InterruptedException {
        Thread joinThread = new Thread(() -> {
            Thread runnableThread = new Thread(() -> {
                while (true) {

                }

            }, "runnable 线程.");
            runnableThread.start();
            try {
                runnableThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "等待join的线程 状态的线程");
        joinThread.start();
    }

监控实例

runnable线程状态

java thread cpu 确认 java thread state_并发编程_04

join线程状态 

java thread cpu 确认 java thread state_线程状态_05

LockSupport.park实例

private static void lockSupport() {
        new Thread(() -> {
            LockSupport.park();
        }, "lockSupport 线程。").start();
    }

 监控状态

java thread cpu 确认 java thread state_Java_06

TIMED_WAITING

timed_waiting状态有调用5个方法中的一种,就会出现,Thread.sleep,Object#wait(long) ,join(long) ,LockSupport#parkNanos ,LockSupport#parkUntil

thread.sleep

用的就比较多,我就不多说了,示例代码。提一点,TimeUnit.SECONDS.sleep(1000*60);这样写也是可以的

private static void sleep() {
        new Thread(() -> {
            try {
                Thread.sleep(60 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "sleep 线程。").start();
    }

控制台 

java thread cpu 确认 java thread state_并发编程_07

Object.wait(long)

对象毫秒等待

private static void objectWait() {
        Object object = new Object();
        new Thread(() -> {
            synchronized (object) {
                try {
                    object.wait(1000 * 60);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "object.wait 线程。").start();
    }

监控

java thread cpu 确认 java thread state_java thread cpu 确认_08

Thread.join(long)

毫秒等待线程线程结束

private static void timedJoin() throws InterruptedException {
        Thread joinThread = new Thread(() -> {
            Thread runnableThread = new Thread(() -> {
                while (true) {
                }

            }, "runnable 线程.");
            runnableThread.start();
            try {
                runnableThread.join(1000 * 60);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "等待join的线程状态的线程");
        joinThread.start();
    }

监控状态

runnable线程状态

java thread cpu 确认 java thread state_并发编程_09

join线程状态 

java thread cpu 确认 java thread state_java thread cpu 确认_10

LockSupport.parkNanos(long)

纳秒时间等待,1000000000纳秒=1秒在java中数值类型可以加下划线在java1.5中的特性比如: int i = 1_00;double d = 1.00_01d;这样写是合法的,便于阅读。

private static void lockSupoortNanosObject() throws InterruptedException {
        final Object object = new Object();
        Thread lockSupportObjectThread = new Thread(() -> {
            //停顿60s
            LockSupport.parkNanos(object, 1000_000_000L * 60);
        }, "lockSupportObjectThread 线程");
        lockSupportObjectThread.start();
    }

监控状态

java thread cpu 确认 java thread state_Java_11

LockSupport.parkUntil

等待绝对时间,直到什么时刻为止,实例代码等待距现在60s

private static void lockSupportParkUntil() {
        Thread thread = new Thread(()->{
            LockSupport.parkUntil(System.currentTimeMillis()+1000*60);
        },"lockSupportParkUtil 线程");
        thread.start();
    }

监控

java thread cpu 确认 java thread state_Java_12

总结

这一讲主要对java的5中线程状态做了实例说明,这里需要注意一点小细节,在创建线程的时候,务必带上名称,方便监控,下一讲,我们进入线程的使用,包括线程的状态转移。