线程的状态

首先了解一下什么是线程的状态,线程状态就是当线程被创建(new),并且启动(start)后,它不是一启动就进入了执行状态(run),也不是一直都处于执行状态。

这里说一下Java 的Thread类里面有一个State方法,这个方法里面涵盖了6种线程的状态,如下:

  1. public enum State {
  2. // 尚未启动的线程的线程状态。
  3. NEW,
  4.  
  5. // 可运行线程的线程状态。
  6. RUNNABLE,
  7.  
  8. // 线程的线程状态被阻塞,等待监视器锁定。
  9. BLOCKED,
  10.  
  11. // 等待线程的线程状态。
  12. WAITING,
  13.  
  14. // 具有指定等待时间的等待线程的线程状态。
  15. TIMED_WAITING,
  16.  
  17. // 终止线程的线程状态。
  18. TERMINATED;
  19. }

导致这六种线程状态发生的条件

New -- 新建

线程刚被创建,不过还没有被启动(还没有调用start方法)

Runnable -- 可运行

处于可运行状态的线程正在Java虚拟机中执行,但是它可能正在等待来自操作系统(例如处理器)的其他资源。

Blocked -- 锁阻塞

当一个线程想获取一个对象锁,不过该对象锁被其它的线程持有时,该线程就会进入锁阻塞状态;当该线程持有锁的时候,该线程将会变成可运行的状态。

Waiting -- 无限等待

当一个线程在等待另一个线程执行一个(唤醒)动作时,该线程就会进入无限等待状态。进入这个状态后是不能自动唤醒的,要等待另一个线程调用notify()方法,或notifyall()方法才能够被唤醒。

Timed_Waiting -- 计时等待

类似于无限等待状态,有几个方法有超时参数,如:Thread.sleep、Object.wait方法。调用这些方法,进入计时等待状态。计时等待状态将会一直保持到超时期满或者接收到唤醒通知。

terminated -- 被终止

1、因为run方法的正常退出而死亡。

2、因为没有捕获的异常,终止了run方法而死亡。

等待唤醒案例切入

顾客要去饭店吃饭,自助下单,说明要吃什么,数量是多少。下完单以后,顾客就等待该饭店厨师做饭菜,也就是Waiting状态(无限等待状态)。

厨师收到下单信息,开始做饭菜,做好饭菜,把饭菜递到顾客桌面上,顾客看到饭菜已经来了(notify方法),就可以开吃了(等待唤醒机制)。

Java代码实现(线程之间的通信)

分析

创建一个顾客线程:下单,告知厨师要什么菜,菜的数量,调用wait方法,放弃CPU的执行,进入到无限等待状态(Waiting)

创建一个厨师线程:看到下单,花了3秒钟做饭菜,做好之后,调用notify方法,唤醒顾客吃饭了。

注意

顾客线程和厨师线程,必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行。

同步使用的锁对象必须保证唯一。

只有锁对象才能够调用Object.wait方法和Object.notify方法。

代码

  1. public class Demo01WaitNotify {
  2. public static void main(String[] args) {
  3. // 创建锁对象(要保证锁唯一)
  4. Object object = new Object();
  5.  
  6. // 创建一个顾客线程
  7. new Thread() {
  8. @Override
  9. public void run() {
  10. // 使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行。
  11. synchronized (object) {
  12. // 顾客下单
  13. System.out.println("我要一个西虹市炒番茄,一个马铃薯炒土豆,两碗米饭");
  14. // 调用wait方法,放弃CPU的执行,进入到无限等待状态(Waiting)
  15. try {
  16. object.wait();
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. // 唤醒之后(饭菜上来后),吃饭!!!真香。
  21. System.out.println("我就是饿死,从这里跳下去,也不会吃你们一口饭。。。真香!!!!");
  22. }
  23. }
  24. }.start();
  25.  
  26. // 创建一个厨师线程
  27. new Thread() {
  28. @Override
  29. public void run() {
  30. // 厨师收到下单请求,花三秒钟把饭菜做好
  31. try {
  32. Thread.sleep(3000);
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. }
  36. // 使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行。
  37. synchronized (object) {
  38. System.out.println("我的饭菜三秒钟做好了,你食唔食哦?");
  39. // 做好之后,调用notify方法,唤醒顾客吃饭了。
  40. object.notify();
  41. }
  42. }
  43. }.start();
  44. }
  45. }
  1. 控制台输出:
  2. 我要一个西虹市炒番茄,一个马铃薯炒土豆,两碗米饭
  3. 我的饭菜三秒钟做好了,你食唔食哦?
  4. 我就是饿死,从这里跳下去,也不会吃你们一口饭。。。真香!!!!

上面的代码,存在线程间的通信,那什么又是线程间的通信呢?简单的说,就是多个线程在处理同一个资源,但是处理的动作(线程的任务)却不同。如上,厨师线程做饭菜,顾客线程吃饭菜。那为什么要进行线程间的通信呢?多个线程并发执行的时候,在默认情况下CPU是随机切换线程的,当我们需要多个线程来共同完成一件任务,并且希望它们有规律的执行的时候,那么多线程就之间就需要一些协调通信,来达到多线程共同操作一份数据。

对代码中通信的理解:

对又没有饭菜进行判断——

1、没有饭菜(False)。

2、顾客下单。

3、厨师做饭菜。

4、顾客线程等待。

5、厨师做好饭菜

6、修改饭菜的状态(True)

7、有饭菜,厨师线程提醒顾客线程吃饭菜。

8、厨师线程等待

9、吃完饭菜,修改饭菜的状态(False)

这就是顾客线程与厨师线程之间的通信。以此类推,其它Java程序中多线程的通信也是同样的道理。

Java 中的等待唤醒机制就解析到这里了,如果有什么不足、错误的地方,希望大佬们指正。

Java 中的等待唤醒机制透彻讲解的更多相关文章

  1. 多线程之Java中的等待唤醒机制

    多线程的问题中的经典问题是生产者和消费者的问题,就是如何让线程有序的进行执行,获取CPU执行时间片的过程是随机的,如何能够让线程有序的进行,Java中提供了等待唤醒机制很好的解决了这个问题! 生产者消 ...

  2. Java中的等待唤醒机制—至少50%的工程师还没掌握!

    这是一篇走心的填坑笔记,自学Java的几年总是在不断学习新的技术,一路走来发现自己踩坑无数,而填上的坑却屈指可数.突然发现,有时候真的不是几年工作经验的问题,有些东西即使工作十年,没有用心去学习过也不 ...

  3. java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

     *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...

  4. Java学习:等待唤醒机制

    等待唤醒机制 线程的状态 NEW   至今尚未启动的线程处于这种状态 RUNNABLE   正在Java虚拟机中执行的线程处于这种状态 BLOCKED 受阻塞并等待某个监视器锁的线程处于这种状态 WA ...

  5. java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)

    1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以 ...

  6. java基础-多线程 等待唤醒机制

       /**  * @param args  * 等待唤醒机制  */ public static void main(String[] args) {  final Printer p = new ...

  7. java锁在等待唤醒机制中作用

    等待的线程放在线程池wait().notify().notifyall()都使用在同步中,因为要对持有监视器(锁)的线程操作.所以要使用在同步中,因为只有同步才具有锁. 为什么这些操作的线程的方法要定 ...

  8. java多线程的等待唤醒机制及如何解决同步过程中的安全问题

    /* class Person{ String name; String sex; boolean flag = true; public void setPerson(String name, St ...

  9. Android(java)学习笔记71:生产者和消费者之等待唤醒机制

    1. 首先我们根据梳理我们之前Android(java)学习笔记70中关于生产者和消费者程序思路: 2. 下面我们就要重点介绍这个等待唤醒机制: (1)第一步:还是先通过代码体现出等待唤醒机制 pac ...

随机推荐

  1. CSS 伸缩布局

    转载于:https://blog.csdn.net/weixin_41342585/article/details/80140513 1. flex-direction:设置伸缩容器中成员的排列方式 ...

  2. P1007 N钱M鸡问题

    题目描述 已知公鸡 \(5\) 元钱一只,母鸡 \(3\) 元钱一只,小鸡 \(3\) 只 \(1\) 元钱. 告诉你一个整数 \(n(1 \le n \le 1000)\) ,你现在要花 \(n\) ...

  3. 浅谈vue $mount()

    Vue 的$mount()为手动挂载,在项目中可用于延时挂载(例如在挂载之前要进行一些其他操作.判断等),之后要手动挂载上.new Vue时,el和$mount并没有本质上的不同. 具体见代码: 顺便 ...

  4. vue-learning:26 - component - 组件三大API之一:prop

    组件三大API之一: prop prop的大小写 prop接收类型 字符串数组形式 对象形式: type / required / default / validator prop传递类型: 静态传递 ...

  5. 记一次奇葩事——html5可能不支持window.onscroll函数

    只在html5里遇到,html4没事:拿出来聊聊,路过帮忙解答下!!! 不正常的 <!doctype html><html><head><meta chars ...

  6. win7+oracle11,vmbox中winxp连接

    重启TNSLSNR  打开CMD,输入以下命令. lsnrctl stop lsnrctl start lsnrctl stat /////////////////////////////////// ...

  7. kali机获取不到ip地址解决

    一.方法一 重启网卡:/etc/init.d/networking restart 重启kali:reboot 二.方法二 更改网络适配器:虚拟机-可移动设备-网络适配器设置-选择“桥接模式:直接连接 ...

  8. 拒绝FileNotFoundException!总结了这几个读取jar包外配置文件的知识点

    前言 相信很多人遇到过这个问题:本地运行的好好的程序,怎么部署到线上就报找不到配置呢? 初识getResource 案例一 FieldMapConfig.class.getResource(" ...

  9. element-ui table 的翻页记忆选中

    公司中台项目刚开始开发,用了vue+element,需要许多前置调研,table的翻译记忆选中就是其中之一. template: <el-table :ref="tableRef&qu ...

  10. AbstractRoutingDataSource动态数据源切换

    操作数据一般都是在DAO层进行处理,可以选择直接使用JDBC进行编程(http://blog.csdn.net/yanzi1225627/article/details/26950615/) 或者是使 ...