Java线程的wait(), notify()和notifyAll()
Java线程生命周期

类java.lang.Thread包含一个静态的State enum用于定义每种可能的状态. 在任意的时间点, 线程会处于以下的状态之一:
NEW – 新创建的线程, 还未启动(在调用 start() 之前的状态). A thread that has not yet started is in this state.
RUNNABLE – 正在运行或已经准备好运行但是在等待资源. either running or ready for execution but it’s waiting for resource allocation
BLOCKED – 在等待获取一个monitor lock来进入或重新进入同步的代码块或方法 waiting to acquire a monitor lock to enter or re-enter a synchronized block/method
WAITING – 在等待其他线程执行一个特定的操作, 没有时间限制 waiting for some other thread to perform a particular action without any time limit
由这三种方法之一进入
object.wait()
thread.join()
LockSupport.park()
TIMED_WAITING – 在某个时间限制内, 等待其他线程执行一个特定的操作 waiting for some other thread to perform a specific action for a specified period
由这五种方法之一进入
thread.sleep(long millis)
wait(int timeout) or wait(int timeout, int nanos)
thread.join(long millis)
LockSupport.parkNanos
LockSupport.parkUnti
TERMINATED – 运行已经结束或意外终止 has completed its execution
wait(), notify()和notifyAll()方法用于在线程间建立关联. 在对象上调用wait()将使线程进入WAITTING状态, 直到其他线程对同一个对象调用notify()或notifyAll(). 在任何线程上, 对一个对象调用wait(), notify()和notifyAll(), 都需要先获得这个对象的锁, 就是说, 这些方法必须在synchronized方法或代码块中调用.
wait()
在对象上调用wait(), 会使当前线程进入等待状态, 直至另一个线程对这个对象调用了notify() 或notifyAll() 方法. 换句话说, 就是简单的执行了wait(0)方法.
在调用wait()时, 当前线程必须拥有这个对象的monitor. 调用后, 线程会释放对象的monitor, 并一直等待直到另一个线程通过notify()或notifyAll()唤醒正在等待这个对象的monitor的线程们. 然后线程会一直等待直到重新拿回这个对象的monitor, 然后才能继续运行.
对于带参数的版本, 中断和唤醒都是可能的, 这个方法必须在一个循环中使用.
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
.
notify()
唤醒正在等待这个对象的monitor的线程中的一个. 如果有多个线程正在等待, 会选择其中的一个, 这个选择是任意的, 因具体实现而不同. 唤醒的线程并不会立即继续执行, 它需要获得这个对象的锁之后才能继续执行. 唤醒的对象将与其他正在竞争这个对象的锁的线程一起竞争对象的锁.
这个方法只允许在拥有当前对象的monitor的线程上调用, 一个线程要得到对象的monitor, 只能通过以下三种方法之一:
- 执行这个对象的一个同步方法
- 执行这个对象中的一段同步代码
- 对于type类型的对象, 执行这个类的一个静态同步方法
在同一时刻, 只允许一个线程得到一个对象的monitor
调用notify()时, 在所有WAITING状态的线程中只会有一个线程被通知, 这个选择是随机的, 被通知的线程并不会立即得到对象的锁, 而是一直等到调用notify()的线程释放锁, 在这之前线程都是BLOCKED状态. 当获得锁后, 就会从BLOCKED状态变为RUNNING状态. 例子
class Shared {
synchronized void waitMethod() {
Thread t = Thread.currentThread();
System.out.println(t.getName() + " is releasing the lock and going to wait");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t.getName() + " has been notified and acquired the lock back");
}
synchronized void notifyOneThread() {
Thread t = Thread.currentThread();
notify();
System.out.println(t.getName() + " has notified one thread waiting for this object lock");
}
}
public class MainClass {
public static void main(String[] args) {
final Shared s = new Shared();
//Thread t1 will be waiting for lock of object 's'
Thread t1 = new Thread() {
@Override
public void run() {
s.waitMethod();
}
};
t1.start();
//Thread t2 will be waiting for lock of object 's'
Thread t2 = new Thread() {
@Override
public void run() {
s.waitMethod();
}
};
t2.start();
//Thread t3 will be waiting for lock of object 's'
Thread t3 = new Thread() {
@Override
public void run() {
s.waitMethod();
}
};
t3.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Thread t4 will notify only one thread which is waiting for lock of object 's'
Thread t4 = new Thread() {
@Override
public void run() {
s.notifyOneThread();
}
};
t4.start();
}
}
.
notifyAll()
当线程在对象上调用notifyAll()时, 所有WAITING状态的线程都会被唤醒, 所有的线程都会从WAITING状态变成BLOCKED状态, 然后争抢对象的锁. 得到对象锁的线程, 将变成RUNNING状态, 而其他线程则继续保持BLOCKED状态继续等待获取对象锁. 例子
class Shared {
synchronized void waitMethod() {
Thread t = Thread.currentThread();
System.out.println(t.getName() + " is releasing the lock and going to wait");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t.getName() + " has been notified and acquired the lock back");
}
synchronized void notifyAllThread() {
Thread t = Thread.currentThread();
notifyAll();
System.out.println(t.getName() + " has notified all threads waiting for this object lock");
}
}
public class MainClass {
public static void main(String[] args) {
final Shared s = new Shared();
//Thread t1 will be waiting for lock of object 's'
Thread t1 = new Thread() {
@Override
public void run() {
s.waitMethod();
}
};
t1.start();
//Thread t2 will be waiting for lock of object 's'
Thread t2 = new Thread() {
@Override
public void run() {
s.waitMethod();
}
};
t2.start();
//Thread t3 will be waiting for lock of object 's'
Thread t3 = new Thread() {
@Override
public void run() {
s.waitMethod();
}
};
t3.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Thread t4 will notify all threads which are waiting for lock of object 's'
Thread t4 = new Thread() {
@Override
public void run() {
s.notifyAllThread();
}
};
t4.start();
}
}
.
一个生产者和消费者的例子
注意, 在1个生产1个消费的情况下, 是能确保生产和消费的互相通知的, 但是在2个生产1个消费的情况下, 有可能要多次notify后消费线程才能拿到queue的锁.
public class DemoThreadWait1 {
Queue<Integer> queue = new LinkedList<>();
public void consume() {
synchronized (queue) {
while (queue.isEmpty()) {
try {
System.out.println("consume wait");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("remove all");
queue.clear();
queue.notify();
}
}
}
public void produce(int i) {
synchronized (queue) {
if (queue.size() < 5) {
System.out.println("add " + i);
queue.add(i);
}
if (queue.size() >= 5) {
queue.notify();
try {
System.out.println("produce wait");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
DemoThreadWait1 demo = new DemoThreadWait1();
new Thread(()->{
while(true) {
demo.consume();
}
}).start();
new Thread(()->{
while(true) {
demo.produce((int) (Math.random() * 1000));
}
}).start();
new Thread(()->{
while(true) {
demo.produce((int) (Math.random() * 1000));
}
}).start();
}
}
Java线程的wait(), notify()和notifyAll()的更多相关文章
- 线程:Java中wait、notify、notifyAll使用详解
基础知识 首先我们需要知道,这几个都是Object对象的方法.换言之,Java中所有的对象都有这些方法. public final native void notify(); public final ...
- java线程学习之notify方法和notifyAll方法
notify(通知)方法,会将等待队列中的一个线程取出.比如obj.notify();那么obj的等待队列中就会有一个线程选中并且唤醒,然后被唤醒的队列就会退出等待队列.活跃线程调用等待队列中的线程时 ...
- Java多线程中wait, notify and notifyAll的使用
本文为翻译文章,原文地址:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example 在Java的Obje ...
- Java Thread wait、notify与notifyAll
Java的Object类包含了三个final方法,允许线程就资源的锁定状态进行通信.这三个方法分别是:wait(),notify(),notifyAll(),今天来了解一下这三个方法.在任何对象上调用 ...
- 关于java的wait、notify、notifyAll方法
wait.notify.notifyAll 遇到的问题 之前开发打印机项目,因为需要使用多线程技术,当时并不怎么理解,一开始随意在方法体内使用wait.notify.notifyAll 方法导致出现了 ...
- Java面试题之notify和notifyAll的区别
锁池: 假设线程A已经拥有对象锁,线程B.C想要获取锁就会被阻塞,进入一个地方去等待锁的等待,这个地方就是该对象的锁池: 等待池: 假设线程A调用某个对象的wait方法,线程A就会释放该对象锁,同时线 ...
- java 关于wait,notify和notifyAll
public synchronized void hurt() { //... this.wait(); //... } public synchronized void recover() { // ...
- java线程总结2--wait/notify(all)/sleep以及中断概念
上一篇关于线程的博客简单梳理了一下多线程的一些基本概念,今天这篇博客再进行多线程编程中一些核心的方法进行简单的梳理和总结,主要是wait,sleep和notify方法以及中断的概念 一.中断概念. 在 ...
- Java线程与多线程教程
本文由 ImportNew - liken 翻译自 Journaldev. Java线程是执行某些任务的轻量级进程.Java通过Thread类提供多线程支持,应用可以创建并发执行的多个线程. 应用 ...
随机推荐
- 【OGG】OGG简单配置双向复制(三)
[OGG]OGG简单配置双向复制(三) 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O ...
- C语言开发具有可变长参数的函数的方法
学习交流可加 微信读者交流①群 (添加微信:coderAllen) 程序员技术QQ交流①群:736386324 --- 前提:ANSI C 为了提高可移植性, 通过头文件stdarg.h提供了一组方便 ...
- Linux操作系统-CentOS6启动流程和服务管理
Linux操作系统-CentOS6启动流程和服务管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Linux组成 1>.Linux: kernel+rootfs ker ...
- String,StringBuffer,StringBuilder区别(笔记)
String类被final修饰,创建的对象为不可变对象,属于字符串常量. 而StringBuffer与StringBuilder创建的属于字符串常量. StringBuffer的方法大多用了Synch ...
- C++——STL(算法)
以下对所有算法进行细致分类并标明功能:<一>查找算法(13个):判断容器中是否包含某个值adjacent_find: 在iterator对标识元素范围内,查找一对相邻重复元素,找到则返 ...
- moviepy的常见用法
看了,还是自己弄这些方便. #字幕 >>> from moviepy.video.tools.subtitles import SubtitlesClip >>> ...
- 数组,字符串,json互相转换
数组转字符串 var arr = [1,2,3,4,'巴德','merge']; var str = arr.join(','); console.log(str); // 1,2,3,4,巴德,me ...
- springboot无法识别配置文件级解决办法
eclipse中右键项目bulid path 之后找到 后点击完成后点击运用 修改完成
- springboot 整合Swagger2的使用
Swagger2相较于传统Api文档的优点 手写Api文档的几个痛点: 文档需要更新的时候,需要再次发送一份给前端,也就是文档更新交流不及时. 接口返回结果不明确 不能直接在线测试接口,通常需要使用工 ...
- danci
plain 英 [pleɪn] 美 [plen] adj. 平的:简单的:朴素的:清晰的 n. 平原:无格式:朴实无华的东西 adv. 清楚地:平易地 n. (Plain)人名:(英)普莱恩:(法)普 ...