java线程状态变迁图

从图中可以看出Java 线程等待方法是将线程从Runnable状态转换为Waiting状态,Java线程的唤醒方法是将线程从Waiting状态唤醒进入Runnable状态

在Java中线程的等待和唤醒主要是分为3组:

  • Object.wait() 和 Object.notify()
  • LockSupport.park() 和 LockSupport.unpark(Thread thread)
  • Condition.await() 和 Condition.signal() ---- 这组内部靠LockSupport.park() 和 LockSupport.unpark(Thread thread) 进行线程等待和唤醒

Object.wait() 和 Object.notify()

wait() 和 notify() 相关方法



表中的方法必须要在获得监视器monitor的情况下使用

简单使用wait()和notify()方法示例:

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
synchronized (object) {
try {
System.out.println("threadA 已进入获得监视器");
object.wait();
System.out.println("threadA 已被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "threadA");
threadA.start();
Thread.sleep(1000);
synchronized (object){
System.out.println("main 已获得监视器");
object.notify();
}
}
}

notify()和notifyAll()的区别演示:使用notify() 只能唤醒一个在对象上等待的线程,使用notifyAll()可以唤醒所有在对象上等待的线程。

使用notify()

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
synchronized (object) {
try {
System.out.println("threadA 已进入获得监视器");
object.wait();
System.out.println("threadA 已被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "threadA"); Thread threadB = new Thread(() -> {
synchronized (object) {
try {
System.out.println("threadB 已进入获得监视器");
object.wait();
System.out.println("threadB 已被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "threadB");
threadA.start();
threadB.start();
Thread.sleep(1000);
synchronized (object){
System.out.println("main 已获得监视器");
object.notify();
System.out.println("main 已唤醒一个线程");
}
}
}



结果线程B未能被唤醒。

改用notifyAll()

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
synchronized (object) {
try {
System.out.println("threadA 已进入获得监视器");
object.wait();
System.out.println("threadA 已被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "threadA"); Thread threadB = new Thread(() -> {
synchronized (object) {
try {
System.out.println("threadB 已进入获得监视器");
object.wait();
System.out.println("threadB 已被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "threadB");
threadA.start();
threadB.start();
Thread.sleep(1000);
synchronized (object){
System.out.println("main 已获得监视器");
object.notifyAll();
System.out.println("main 已唤醒一个线程");
}
}
}



线程A,B都被唤醒了,程序正常结束。

wait(long) 方法的使用: 等待时间过了没被唤醒自己进入Runnable状态

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
synchronized (object) {
try {
System.out.println("threadA 已进入获得监视器");
object.wait(1000 * 60);
System.out.println("threadA 已被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "threadA");
threadA.start();
}
}

程序执行结果



调用wait(long) 方法进入timed_waiting状态



等待时间过了进入runnable状态

注意线程中断也会唤醒wait()中的线程

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
synchronized (object) {
try {
System.out.println("threadA 已进入获得监视器");
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("threadA 已被唤醒");
}
}, "threadA");
threadA.start();
Thread.sleep(1000);
threadA.interrupt();
}
}

程序执行结果

LockSupport.park() 和 LockSupport.unpark(Thread thread)

LockSupport.park() 和 LockSupport.unpark(Thread thread) 并不依赖同步方法

LockSupport.park() 和 LockSupport.unpark(Thread thread) 相关方法

简单使用

public class ParkTest {

    public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
System.out.println("ThreadA 开始运行了");
LockSupport.park();
System.out.println("ThreadA 继续运行了");
}, "ThreadA");
threadA.start();
Thread.sleep(1000 * 5);
LockSupport.unpark(threadA);
}
}

注意线程中断也会唤醒LockSupport.park()中的线程

public class ParkTest {

    public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
System.out.println("ThreadA 开始运行了");
LockSupport.park();
System.out.println("ThreadA 继续运行了");
}, "ThreadA");
threadA.start();
Thread.sleep(1000 * 5);
threadA.interrupt();
}
}

Condition.await() 和 Condition.signal()

Condition.await() 和 Condition.signal() 相关方法

简单使用

public class ConditionTest {

    static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
lock.lock();
try {
System.out.println("线程A 获得了lock锁");
condition.await();
} catch (InterruptedException e) {
System.out.println("线程A 被唤醒了");
e.printStackTrace();
} finally {
lock.unlock();
}
}, "ThreadA");
threadA.start();
Thread.sleep(1000 * 5);
lock.lock();
try {
System.out.println("main 线程获得了lock锁");
condition.signal();
} catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}
}

程序执行结果:

注意线程中断也会唤醒condition.await()中的线程

public class ConditionTest {

    static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args) throws InterruptedException {
Thread threadA = new Thread(() -> {
lock.lock();
try {
System.out.println("线程A 获得了lock锁");
condition.await();
} catch (InterruptedException e) {
System.out.println("线程A 被唤醒了");
e.printStackTrace();
} finally {
lock.unlock();
}
}, "ThreadA");
threadA.start();
Thread.sleep(1000 * 5);
threadA.interrupt();
condition.signal();
}
}

程序执行结果:

Condition.signalAll() 用法上和Object.notifyAll() 类似

参考:《Java并发编程的艺术》

java 线程等待和唤醒方法的更多相关文章

  1. java - 线程等待与唤醒

    Java多线程系列--“基础篇”05之 线程等待与唤醒 概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. w ...

  2. Java线程等待与唤醒

    class ThreadA extends Thread{ public ThreadA(String name) { super(name); } public void run() { synch ...

  3. java 多线程—— 线程等待与唤醒

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  4. Java 多线程基础(六)线程等待与唤醒

    Java 多线程基础(六)线程等待与唤醒 遇到这样一个场景,当某线程里面的逻辑需要等待异步处理结果返回后才能继续执行.或者说想要把一个异步的操作封装成一个同步的过程.这里就用到了线程等待唤醒机制. 一 ...

  5. linux平台,对线程等待和唤醒操作的封装(pthread_cond_timedwait 用法详解)

    前言 linux平台下,线程等待和唤醒操作是很常见的,但是平台函数不易使用:笔者对此操作做了封装,使之更易于使用. 线程等待和唤醒函数比较 平台提供了线程等待相关函数,这些函数之间用法也有些差异: s ...

  6. JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)

    一.前言 在多线程的场景下,我们会经常使用加锁,来保证线程安全.如果锁用的不好,就会陷入死锁,我们以前可以使用Object的wait/notify来解决死锁问题.也可以使用Condition的awai ...

  7. Java多线程系列--“基础篇”05之 线程等待与唤醒

    概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...

  8. Java多线程5:线程等待与唤醒

    原文:http://www.cnblogs.com/skywang12345/p/3479224.html wait(),notify(), notifyAll()等方法介绍在Object.java中 ...

  9. Java多线程(五)——线程等待与唤醒

    一.wait().notify().notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()和notifyAll()等接口.wait()的作用是让当前线程进 ...

  10. java 多线程系列基础篇(五)之线程等待与唤醒

    1.wait(), notify(), notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()和notifyAll()等接口.wait()的作用是让当前线 ...

随机推荐

  1. abp(net core)+easyui+efcore实现仓储管理系统——供应商管理升级之下(六十四)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...

  2. 【Visual C#】基于《斗鱼弹幕服务器第三方接入协议v1.6.2》实现斗鱼弹幕服务器接入

    最近在给某个主播开发斗鱼直播间辅助工具,为了程序的高效稳定,也搜索了大量的资料,经过大量什么百度,谷歌搜索... 虽然有很多Python的脚本及JS脚本实现了拉取斗鱼弹幕信息,但是这些年来的开发职业病 ...

  3. #Python实例 计算外卖配送距离(基于经纬度的导航及直线距离)

    一:X-MIND 二:计算两点经纬度之间的距离 经纬度是利用三维球面空间来描述地球上一个位置的坐标系统,每个经纬度坐标由经度 lng 和纬度 lat 两个分量组成.经纬度的有效范围为经度-180度到+ ...

  4. vue+vant项目中 rem适配配置

    vant rem适配,需要安装两个插件 postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem lib-flexible 用于设置 rem 基准值 postcss-px ...

  5. 2022-12-21:uifd/ui-for-docker是docker的web可视化工具。请问部署在k3s中,yaml文件如何写?

    2022-12-21:uifd/ui-for-docker是docker的web可视化工具.请问部署在k3s中,yaml文件如何写? 答案2022-12-21: yaml如下: apiVersion: ...

  6. Django4全栈进阶之路21 项目实战(在线报修):创建App应用和Model模型

    创建应用App python manage.py startapp RepairApp 创建模型 在models.py文件中定义一个Repair模型来表示报修单,其中包含以下字段: repair_id ...

  7. 代码随想录算法训练营Day44 动态规划

    代码随想录算法训练营 代码随想录算法训练营Day44 动态规划|完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ 完全背包 有N件物品和一个最多能背重量为W的背包.第i件物品的重量是weig ...

  8. ODOO升级模块后到系统进入不了,报错500

    有时候安装后者升级odoo相关模块后会导致系统进入不了,报错500,此时我们可以通过Odoo命令行卸载相关模块 此方法适用于在安装或升级某个模块后导致崩库,进不去桌面的情况下使用.原理是通过odoo- ...

  9. x86 机器指令编码规则

    x86 机器指令编码依次由一下部分组成: 指令前缀(prefix,非必需) 操作码(opcode,必需) 寻址方式 R/M(ModR/M,非必需) 比例因子-变址-基址(SIB,非必需) 地址偏移量( ...

  10. 【问题解决】 网关代理Nginx 301暴露自身端口号

    一般项目上常用Nginx做负载均衡和静态资源服务器,本案例中项目上使用Nginx作为静态资源服务器出现了很奇怪的现象,我们一起来看看. "诡异"的现象 部署架构如下图,Nginx作 ...