java——线程的wait()和notify()
这是一个关于生产者和消费者的线程通信的例子:
package thread_test;
public class PCThread {
public static void main(String[] args) {
Queue q = new Queue();
Producer p = new Producer(q);
Consumer c = new Consumer(q);
p.start();
c.start();
}
}
//被唤醒后的线程到底重新执行同步代码块还是从那是等待的那里继续执行
class Producer extends Thread{
Queue q;
Producer(Queue q){
this.q = q;
}
public void run() {
for(int i = 1 ; i < 5 ; i ++) {
q.put(i);
}
}
}
class Consumer extends Thread{
Queue q;
Consumer(Queue q){
this.q = q;
}
public void run() {
while(true) {
q.get();
}
}
}
class Queue{
int value = 0;
boolean isEmpty = true;
public synchronized void put(int v) {
//如果共享数据没有被消费,则生产者等待
if(!isEmpty) {
try {
System.out.println("生产者等待");
wait();
}catch(Exception e) {
}
}
value += v;
isEmpty = false;
System.out.println("生产者生产数量:" + v);
notify();
}
public synchronized int get() {
if(isEmpty) {
try {
System.out.println("消费者等待");
wait();
}catch(Exception e) {
}
}
value --;
if(value < 1) {
isEmpty = true;
}
System.out.println("消费者消费一个,剩余:" + value);
notify();
return value;
}
}
执行结果:

我想不通为什么当消费者消费了一个之后,已经触发了notify(),为什么生产者没有开始生产,而是知道剩余为0 时才继续生产?
这个问题我居然想了好久。。。
原因:
notify/notifyAll() 的执行只是唤醒沉睡的线程,而不会立即释放锁。消费者消费一个产品后触发了notify()但此时这个消费者线程并没有释放锁,这个时候生产者线程虽然被唤醒,但是由于没有得到锁,仍然不能继续执行。
当剩余商品为0 时,isEmpty为true,消费者线程执行到了wait()方法,这时候当前的锁被释放,消费者线程让出CPU,进入等待状态。被唤醒的生产者线程拿到了这个锁,继续执行自己的线程。
java——线程的wait()和notify()的更多相关文章
- Java线程通信——wait() 和 notify()
Object类中有关线程通信的方法有两个notify方法和三个wait方法,官方解释: void notify() Wakes up a single thread that is waiting o ...
- java 线程之间通信以及notify与notifyAll区别。
jvm多个线程间的通信是通过 线程的锁.条件语句.以及wait().notify()/notifyAll组成. 下面来实现一个启用多个线程来循环的输出两个不同的语句. package com.app. ...
- JAVA 线程状态以及synchronized,wait,sleep,yield,notify,notifyAll
java线程存在以下几种状态: 1: 创建状态(New):线程被new出来,还未调用start 2: 就绪状态(Runnable):又称为可执行状态,调用线程的start方法后,线程处于就绪状态,,线 ...
- java线程中的sleep/wait/notify/yield/interrupt方法 整理
java线程中的sleep/wait/notify/yield/interrupt方法 sleep 该方法能够使当前线程休眠一段时间 休眠期间,不释放锁 休眠时间结束之后,进入可执行状态,加入到线程就 ...
- (删)Java线程同步实现一:synchronzied和wait()/notify()
上面文章(2.Java多线程总结系列:Java的线程控制实现)讲到了如何对线程进行控制,其中有一个是线程同步问题.下面我们先来看一个例子: 1.一个典型的Java线程安全例子 package com. ...
- 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型
关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...
- 【Java 线程的深入研究3】最简单实例说明wait、notify、notifyAll的使用方法
wait().notify().notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态. 这三个方法最终调用的都是jvm级的native方法.随着jvm运行平台的不同可能有些 ...
- Java多线程:线程状态以及wait(), notify(), notifyAll()
一. 线程状态类型1. 新建状态(New):新创建了一个线程对象.2. 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中,变得可运 ...
- Java线程和多线程(二)——对象中的wait,notify以及notifyAll方法
Java对象中的wait,notify以及notifyAll方法 在Java的Object类中包含了3个final的方法,这三个方法允许线程来交流资源是否被锁定.这三个方法就是wait(),notif ...
随机推荐
- Tensorflow递归神经网络学习练习
import tensorflow as tffrom tensorflow.examples.tutorials.mnist import input_data #载入数据集mnist = inpu ...
- beforeFilter()
在控制器每个动作之前执行,可以方便地检查有效的会话,或者检查用户的权限. function beforeFilter() { parent::beforeFilter(); if(empty($thi ...
- XML DTD语法详解
XML DTD详解 XML DTD详解 前情提要与本文内容介绍 前面的两篇XML相关博文: 第一篇是介绍格式正规的XML: 格式正规的XML:语法 属性 实体 处理指令 样式单 CDATA节 第二 ...
- Oracle数据库之多表查询一
上一篇给大家介绍了数据的单表查询,相信大家对于单表的查询应该都有了一些了解.单表查询在数据库中的使用会有一些,但并不是很多,但是作为初学者,我们需要学习单表查询的思路.今天呢,我们为大家介绍一下数据库 ...
- delphi 调用百度地图WEBSERVICE转换GPS坐标
百度地图的API说明 使用方法 第一步,申请密钥(ak),作为访问服务的依据: 第二步,按照请求参数说明拼写发送http请求的url,注意需使用第一步申请的ak: 第三步,接收返回的数据(json或者 ...
- Mac下的UI自动化测试 (一)
在我看来,实现UI自动化测试的过程一向都是令人快乐的事情,而维护它们就是跟噩梦一样了,尤其是对每次CI产生的build进行BVT测试,由于开发不会告诉你任何UI的变化,那么你拿到的测试结果就势必会一片 ...
- BootStrap母版页布局.子页面布局.BootstrapTable.模态框.警告框.html导出tabl生成Excel.HTML生成柱图.饼图.时间控件中文版
如上就是很多后台管理系统的母版页布局. 左边一列模板.上面一列系统标识. 空白处充填子页面 以ASP.NET MVC为基础 引入bootstrap.js.bootstrap.css body: < ...
- javascript 获取标签内的内容
js 获取标签内的内容 参考:这篇博客给了我很大的启发. http://www.cnblogs.com/breakdown/archive/2012/10/09/2716221.html 我遇到的问题 ...
- javascript dom与字符串相互转换
js dom与字符串相互转换 一.字符串转换dom: function stringToDom(str){ var obj=document.createElement("div" ...
- Delphi 关键字详解
Delphi 关键字详解[整理于 "橙子" 的帖子] absolute //它使得你能够创建一个新变量, 并且该变量的起始地址与另一个变量相同. var Str: ]; S ...