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. 100026. 【NOIP2017提高A组模拟7.7】图

    题目大意: 给你n个点,每个点只有一条出路,请问每个点走了k步之后走过的权值和. 权值最小的边的权值. 考场想法: 考试时就先打了个暴力,然后发现一定会形成一个环,所以就想到了可以判环,然后 按照规律 ...

  2. LINUX经常使用的命令详解

    LINUX经常使用的命令详解 源地址:http://blog.itpub.net/29065182/viewspace-1189162/ 1.man 对你熟悉或不熟悉的命令提供帮助解释  eg:man ...

  3. Mac + IOS + Safari 抓取网络请求

    第一步:打开苹果手机 设置>Safari浏览器>高级>网页检查器 第二步:打开 Mac 上的Safari浏览器>偏好设置>高级>在菜单栏中显示"开发&qu ...

  4. NC17383 A Simple Problem with Integers

    题目链接 题目 题目描述 You have N integers A1, A2, ... , AN. You are asked to write a program to receive and e ...

  5. 【必知必会的MySQL知识】③DML语言

    目录 前言 准备 插入数据 语法格式 插入完整行数据 插入多行数据 将检索出来的数据插入表 更新数据 准备两张表 语法 实践操作 删除数据 语法 实践操作 小结 前言 前面的两篇文章中,我们已经对My ...

  6. 小米商城主页展示HTML+CSS

    大佬们呀,花了好几天的时间总算是看着页面展示可以了,求赐教! 小米商城主页,对大佬来说肯定简单爆了,我抄写了好久呀,总是有一点点的小问题,还搞不明白 主要是一个静态的小米商城页面,HTML前端代码不复 ...

  7. 2020-09-06:Docker的命名空间有哪些?

    福哥答案2020-09-06: 福哥口诀法:命进I网挂U用 1.进程命名空间.CLONE_NEWPID.进程编号. 2.IPC 命名空间.CLONE_NEWPIPC.信号量.消息队列何共享内存. 3. ...

  8. Sentinel基本使用与源码分析

    系列文章目录和关于我 一丶什么是Sentinel Sentinel官网 Sentinel 是面向分布式.多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由.流量控制.流量整形.熔断降级 ...

  9. 如何让ChatGPT生成Midjourney提示词

    ​ 导读:最近AI绘画非常的火,今天我们看ChatGPT如何生成Midjourney提示词,让AI教AI做事. 本文字数:900,阅读时长大约:3分钟 正如 Midjourney 的官方网站报道的那样 ...

  10. java中单例模式 如何使用

    引用: 原文链接:https://blog.csdn.net/qq_41458550/article/details/109243456