欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java多线程:线程状态与线程等待唤醒机制的理解

程序员文章站 2022-05-04 18:09:36
...

写在前面

2020年疫情以来,坚持在csdn博客写文章已经有两个多月了,刚开始动笔的原因,主要就是为了把一些知识点及工作中碰到的问题,通过博客的方式记录下来,但随着时间的加长,对于写博客也有了一些新的认识,今天借这个机会,把个人想法记录在案:

刚开始的想法
  • 刚开始写的时候担心自己坚持不下来
  • 动笔了感觉没什么写,内容不充实
  • 在互联网上写博客,总是要被人看的,怕被人笑话

  • 在内心忐忑之间,还是坐下来写了,反正写的都是技术文:从书上学到的,工作中碰到的,确有其事;文章中的样例代码,都是自己手把手写的且通过调试运行,贵在真实。
现在的心境

不以成为职业作家为目标的话,写文章其实没那么难。某种程度上,它就跟我们平时说话、唱歌一样,只是一种沟通交流的手段,源自我们与生俱来的表达欲望。

慢慢地,写博客成了近几个月的习惯,几天不码字感觉少了点什么:

  • 把技术通过文字的形式写下来更容易理清逻辑,加深认知;
  • 把知识点通过系列文章分段的方式写下来,是对思维的刻意训练;
  • 坚持写博客,整理技术素材,能做到温故而知新;
  • 通过互联网的传播,通过网友的点评,更加能鞭策作者。

废话到此为止,接下来进入正题。

线程状态概述

java线程在运行的生命周期有6种不同的状态,在给定的一个时刻,线程只能处于其中的一个状态。

状态 说明
NEW 新建状态又称为初始状态,线程刚被创建,但没调用start()开始运行
RUNNABLE 运行状态,java线程将操作系统中就绪和运行状态统称为”运行中“状态
BLOCKED 阻塞状态,线程被”锁“阻塞时的状态
WAITING 等待状态又称为永久等待状态,处于永久等待状态的线程需要被其他线程唤醒或中断
TIMED_WAITING 休眠等待状态又称为计时等待状态,处于计时等待状态的线程休眠结束后自行唤醒
TERMINATED 终止状态,线程运行结束

java多线程:线程状态与线程等待唤醒机制的理解

线程的等待与唤醒

  • 创建一个全局的锁对象objectLock;
  • 创建一个线程全局的运行标志flag;
  • 运行线程0,并通过objectLock进行无限等待状态;
  • 运行线程1,并通过objectLock唤醒该锁对象上的等待线程,并将运行标志flag置为结束;
  • 线程0得到唤醒通知后,继续运行,并根据结束标志的状态结束运行。
/**
 * 线程状态--线程等待唤醒状态的相互转换
 *
 * @author zhuhuix
 * @date 2020-05-10
 */
public class ThreadStatus {

    //创建静态锁对象
    static final Object objectLock = new Object();
    //线程结束标志
    static boolean flag = true;

    public static void main(String[] args) throws InterruptedException {
        //调用等待线程执行
        new Thread(new Waiting()).start();
        TimeUnit.SECONDS.sleep(1);
        //调用唤醒线程执行
        new Thread(new Notify()).start();
    }

    /**
     * 等待线程
     */
    static class Waiting implements Runnable {
        @Override
        public void run() {
            synchronized (objectLock) {
                while (flag) {
                    try {
                        System.out.println(Thread.currentThread().getName() + "线程正在等待:"
                                + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS").format(LocalDateTime.now()));
                        objectLock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + "线程完成运行:"
                        + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS").format(LocalDateTime.now()));
            }
        }
    }

    /**
     * 唤醒线程
     */
    static class Notify implements Runnable {
        @Override
        public void run() {
            synchronized (objectLock) {
                System.out.println(Thread.currentThread().getName() + "线程唤醒:"
                        + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS").format(LocalDateTime.now()));
                objectLock.notify();
                flag = false;
            }
        }
    }

}

输出结果:
java多线程:线程状态与线程等待唤醒机制的理解

线程的计时等待

  • 线程在休眠时加上计时,无需再被被其他唤醒,计时时间到了,自行醒来。
/**
 * 线程状态--线程的计时等待
 *
 * @author zhuhuix
 * @date 2020-05-10
 */
public class ThreadWaitAndNotify {
    //创建静态锁对象
    static final Object objectLock = new Object();

    public static void main(String[] args) {
        //调用等待线程执行
        new Thread(new ThreadWaitAndNotify.Waiting()).start();
    }

    /**
     * 等待线程
     */
    static class Waiting implements Runnable {
        @Override
        public void run() {
            synchronized (objectLock) {

                    try {
                        System.out.println(Thread.currentThread().getName() + "线程正在等待:"
                                + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS").format(LocalDateTime.now()));
                        objectLock.wait(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + "线程完成运行:"
                        + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS").format(LocalDateTime.now()));

        }
    }

}


java多线程:线程状态与线程等待唤醒机制的理解

线程等待/唤醒机制的简单总结

等待方:

 synchronized (对象) {
	 while (条件不满足) {
       等待
     }
     运行业务逻辑 
 }

通知方:

 synchronized (对象) {
	   改变条件
       唤醒
 }

等待/唤醒机制的应用–生产者与消费者

  1. 生产者生产披萨,每生产满10个,通知消费者购买。
  2. 消费者购买披萨,若无披萨则等待生产者通知。
/**
 * 线程等待唤醒状态的应用--生产者与消费者问题
 *
 * @author zhuhuix
 * @date 2020-05-10
 */
public class ProduceConsumeThread {

    //创建静态锁对象
    static final Object objectLock = new Object();
    //披萨数量
    static int pizza = 0;

    public static void main(String[] args) {
        //生产者生产披萨
        new Thread(new ProduceConsumeThread.Produce()).start();
        //消费者购买披萨
        new Thread(new ProduceConsumeThread.Consume()).start();
    }

    /**
     * 生产者
     */
    static class Produce implements Runnable {
        @Override
        public void run() {
            while (true) {
                synchronized (objectLock) {
                    if (pizza >= 10) {
                        //通知消费者购买
                        objectLock.notifyAll();
                    } else {
                        pizza++;
                        System.out.println(Thread.currentThread().getName() + "生产出披萨:" + pizza + "个,"
                                + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS").format(LocalDateTime.now()));
                        try {
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    /**
     * 消费者
     */
    static class Consume implements Runnable {
        @Override
        public void run() {
            while (true) {
                synchronized (objectLock) {
                    if (pizza == 0) {
                        try {
                            System.out.println(Thread.currentThread().getName() + "消费者正在等待购买:"
                                    + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS").format(LocalDateTime.now()));
                            objectLock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        pizza--;
                        System.out.println(Thread.currentThread().getName() + "消费者购买披萨," + "披萨还剩" + pizza + "个,"
                                + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS").format(LocalDateTime.now()));
                    }
                }
            }
        }
    }

}

运行结果如下:
java多线程:线程状态与线程等待唤醒机制的理解

相关标签: java 多线程