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. 去中心化金融-Lec2

    Finance Finance is the process that involves the creation, management, and investment of money and f ...

  2. Node工程的依赖包管理方式

    作者:京东零售 陈震 在前端工程化中,JavaScript 依赖包管理是非常重要的一环.依赖包通常是项目所依赖的第三方库.工具和框架等资源,它们能够帮助我们减少重复开发.提高效率并且确保项目可以正确的 ...

  3. MySQL概述与安装

    MySQL数据库 概要: 一.MySQL数据库的概述 二.MySQL数据库的搭建 三.MySQL数据库软件的使用 四.MySQL数据类型 五.MySQL数据库数据的操作 一.初始MySQL数据库 1. ...

  4. \n 和 std::endl 的区别

    std::cout << std::endl; 等价于 std::cout << '\n' << std::flush; 除了写入换行符,std::endl 还会刷 ...

  5. 2022-02-08:k8s安装centos,yaml如何写? 注意:如果不配置参数,centos容器会处于terminated状态。如何让容器处于running状态?

    2022-02-08:k8s安装centos,yaml如何写? 注意:如果不配置参数,centos容器会处于terminated状态.如何让容器处于running状态? 答案2022-02-08: 加 ...

  6. 各类源码下载网址(u-boot,linux,openssl,文件系统)

    一.U-Boot源代码下载 1.U-Boot的官方网站: https://www.denx.de/wiki/U-Boot/http://ftp.denx.de/pub/u-boot/ftp://ftp ...

  7. nc工具利用

    c: 瑞士军刀/网络测评工具    将本地的cmd 权限移交到外网 nc工具:应用    本地cmd打开, 输入  nc -e cmd 远程ip  5577  #连接到远程ip的5577 远程cmd打 ...

  8. 在EXCEL和WPS表格里实现邮件合并功能

    在EXCEL和WPS表格里实现邮件合并功能 2020/3/21 22:06:09 0人评论 10635次 OFFICE邮件合并:在Office中,先建立两个文档:一个WORD包括所有文件共有内容的主文 ...

  9. ODDO之三 :Odoo 13 开发之创建第一个 Odoo 应用

    Odoo 开发通常都需要创建自己的插件模块.本文中我们将通过创建第一个应用来一步步学习如何在 Odoo 中开启和安装这个插件.我们将从基础的开发流学起,即创建和安装新插件,然后在开发迭代中更新代码来进 ...

  10. bugku xxx二手交易市场

    打开靶场 分析 很明显需要先注册一个账号才行 完成后发现两个上传图片的地方 一个是更换头像, 一个是发布内容 先更换头像试试 首先上传一个木马图片,会发现一直转圈圈,(卡住了) 只能先上传正常的图片了 ...