java 线程等待和唤醒方法
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 线程等待和唤醒方法的更多相关文章
- java - 线程等待与唤醒
Java多线程系列--“基础篇”05之 线程等待与唤醒 概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. w ...
- Java线程等待与唤醒
class ThreadA extends Thread{ public ThreadA(String name) { super(name); } public void run() { synch ...
- java 多线程—— 线程等待与唤醒
java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...
- Java 多线程基础(六)线程等待与唤醒
Java 多线程基础(六)线程等待与唤醒 遇到这样一个场景,当某线程里面的逻辑需要等待异步处理结果返回后才能继续执行.或者说想要把一个异步的操作封装成一个同步的过程.这里就用到了线程等待唤醒机制. 一 ...
- linux平台,对线程等待和唤醒操作的封装(pthread_cond_timedwait 用法详解)
前言 linux平台下,线程等待和唤醒操作是很常见的,但是平台函数不易使用:笔者对此操作做了封装,使之更易于使用. 线程等待和唤醒函数比较 平台提供了线程等待相关函数,这些函数之间用法也有些差异: s ...
- JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)
一.前言 在多线程的场景下,我们会经常使用加锁,来保证线程安全.如果锁用的不好,就会陷入死锁,我们以前可以使用Object的wait/notify来解决死锁问题.也可以使用Condition的awai ...
- Java多线程系列--“基础篇”05之 线程等待与唤醒
概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...
- Java多线程5:线程等待与唤醒
原文:http://www.cnblogs.com/skywang12345/p/3479224.html wait(),notify(), notifyAll()等方法介绍在Object.java中 ...
- Java多线程(五)——线程等待与唤醒
一.wait().notify().notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()和notifyAll()等接口.wait()的作用是让当前线程进 ...
- java 多线程系列基础篇(五)之线程等待与唤醒
1.wait(), notify(), notifyAll()等方法介绍 在Object.java中,定义了wait(), notify()和notifyAll()等接口.wait()的作用是让当前线 ...
随机推荐
- Linux 根据名称自动kill掉当前相关进程
ps aux | grep app | grep -v "grep" | awk '{print $2}' | xargs -r kill
- 明解STM32—GPIO应用设计篇之API函数及配置使用技巧
一.前言 本篇开始对STM32的GPIO在实际开发设计中的使用配置和技巧进行探讨,可以先去回顾下之前介绍的GPIO的相关理论基础知识包括基本结构,工作模式和寄存器原理. 了解过STM32的GPIO相关 ...
- C# 编译异常CS0433
编译后遇到nuget版本冲突: error CS0433: 类型"ShellFile"同时存在于"Microsoft.WindowsAPICodePack.Shell, ...
- Python变量的数据类型
主要内容 jupyter notebook的用法 变量 跟vi/vim的编辑模式很像 # 声明的三种格式 # 格式1 s1 = "我爱王晓静" # 格式2 s2 = s1 = &q ...
- 2021-11-19:[0,4,7] : 0表示这里石头没有颜色,如果变红代价是4,如果变蓝代价是7,[1,X,X] : 1表示这里石头已经是红,而且不能改颜色,所以后两个数X无意义,[2,X,X]
2021-11-19:[0,4,7] : 0表示这里石头没有颜色,如果变红代价是4,如果变蓝代价是7,[1,X,X] : 1表示这里石头已经是红,而且不能改颜色,所以后两个数X无意义,[2,X,X] ...
- 树莓派上使用docker部署aria2,minidlna
目前在树莓派上安装aria2跟minidlna能搜到的教程基本上都是直接apt-get install安装的.现在是docker的时代了,其实这2个东西可以直接使用docker run跑起来.有什么问 ...
- 使用 React Three Fiber 和 GSAP 实现 WebGL 轮播动画
参考:Building a WebGL Carousel with React Three Fiber and GSAP 在线 demo github 源码 效果来源于由 Eum Ray 创建的网站 ...
- WPF入门实例 WPF完整例子 WPF DEMO WPF学习完整例子 WPF实战例子 WPF sql实例应用 WPF资料源码
WPF 和 WinForms 都是用于创建 Windows 桌面应用程序的开发框架,它们有一些相似之处,但也有很多不同之处. 在开发速度方面,这取决于具体情况.如果您熟悉 WinForms 开发并且正 ...
- 玩转服务器之网站篇:新手使用WordPress搭建博客和静态网站部署
静态网站部署和WordPress搭建博客都是网站运营中常见的工作.静态网站是一种不需要服务器端脚本的网站形式,通常使用HTML.CSS和JavaScript等静态资源进行构建和显示.而WordPres ...
- Vulhub靶场的搭建
Vulhub靶场的搭建(基于centos7) 1>简述 很多人在搭建Vulhub靶场的时候,可能也搜到过许多的文章,但是大多数的文章只是有一个流程,对其中的原理,步骤没有进行详细的说明,这也就导 ...