Java基础教程:多线程基础——线程的状态

Java基础教程:多线程基础——线程的状态

线程的状态

  在Java中,线程有6种状态,分别为:

  • 初始:NEW
  • 运行:RUNNABLE
  • 阻塞:BLOCKED
  • 等待:WAITING
  • 超时等待:TIMED_WAIT
  • 终止:TERMINAL

  这六种状态分别对应于Thread.State中的枚举类型。可以用下面这张图来解释一下Java中的线程的状态转换

  

初始态

  初始态表示一个线程刚被初始化,即new Thread()

Thread thread = new Thread();
System.out.println(thread.getState());

//Output:NEW

  这个没什么好说的,也是最简单。

运行态

  当调用一个Thread对象的start方法后,该线程进入运行态。运行态的名字是很有迷惑性的,其实运行态再细分还可以分为两个子状态:

  • Ready:调用start后,该线程放入可运行线程池中,等待被调度,获得CPU运行权
  • Running:获得CPU时间片后变为运行中状态

  也即是就绪和运行中都是运行态,一定要谨记!

阻塞态

  阻塞态可能理解就要上一个台阶了,阻塞态表示一个线程因为等待临界区的锁而被阻塞产生的状态。我们举一个例子,我们有一个上锁的单人厕所,有两个人同时要求上厕所,但是有一个人抢先进去了,然后反锁了,第二个就在厕所门口等着,他就属于阻塞态。此时又来了第三个人、第四个等等,他们都属于阻塞态,只有第一个出来,下一个进去的才能摆脱这个状态!

  话不多说,我们写代码来实现这情形,在这里用了Lambda表达式来简写线程的run方法。

public class BlockedDemo {
    public static void main(String[] args) throws InterruptedException {
        Toilet room = new Toilet();
        Thread a = new Thread(() -> room.use());
        a.start();
        Thread.sleep(1000);
        Thread b = new Thread(() -> room.use());
        b.start();
        Thread.sleep(2000);
        System.out.println(b.getState());
    }

}

class Toilet{
    synchronized void use(){
        try {
            Thread.sleep(7000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

  此时打印出来的状态就是:BLOCKED状态!

等待态与超时等待态

  当我们拿到锁执行方法的时候,我们可能由于某些原因,还是以厕所为例,发现没带纸,我们需要出去,这时肯定不能霸占厕所,所以我们要主动出去,遂调用wait方法后,让出锁,我们就处于等待状态。如果送纸的人来了,再把我们唤醒notify。

public class WaitingDemo {
    public static void main(String[] args) throws InterruptedException {
        WaitToilet room = new WaitToilet();
        Thread a = new Thread(() -> room.use());
        a.start();
        Thread.sleep(100);
        System.out.println(a.getState());
    }

}

class WaitToilet{
    synchronized void use(){
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

  你可以看到wait(long time)有一个参数指定时间,表示我们先出去等time时间,然后再排队如厕,此时我们就处于超时等待状态。如果送纸的人迟迟不来,也不等了,

我们再来简单总结一下:

  • 一个线程A在拿到锁但不满足执行条件的时候,需要另一个线程B去满足这个条件,那么线程A就会释放锁并处于waiting的状态,等线程B执行完再执行。
  • waiting状态的好处是:此状态的线程不再活动,不再参与调度,因此不会浪费 CPU 资源,也不会去竞争锁了,相比暴力的blocking状态,要优雅很多
  • 如果设置等待时间的话,超过时间,会自动被唤醒

终止状态

  线程所有逻辑执行完了,就处于终止状态。这个和初始态一样都是好理解的!

原文地址:https://www.cnblogs.com/MrSaver/p/12398951.html