Java中wait()和notify()方法的使用
1. wait方法和notify方法
这两个方法,包括notifyAll方法,都是Object类中的方法。在Java API中,wait方法的定义如下:
public final void wait()
throws InterruptedExceptionCauses the current thread to wait until another thread invokes thenotify()method or thenotifyAll()method for this object. In other words, this method behaves exactly as if it simply performs the callwait(0).The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the
notifymethod or thenotifyAllmethod. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}This method should only be called by a thread that is the owner of this object's monitor. See the
notifymethod for a description of the ways in which a thread can become the owner of a monitor.
在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信。线程在运行的时候,如果发现某些条件没有被满足,可以调用wait方法暂停自己的执行,并且放弃已经获得的锁,然后进入等待状态。当该线程被其他线程唤醒并获得锁后,可以沿着之前暂停的地方继续向后执行,而不是再次从同步代码块开始的地方开始执行。但是需要注意的一点是,对线程等待的条件的判断要使用while而不是if来进行判断。这样在线程被唤醒后,会再次判断条件是否正真满足。
想象一下一个生产者,多个消费者的场景。一个消费者Consumer1了最后一个元素,并且唤醒了其他线程,如果被唤醒的正好是Consumer2,那么此时是没有元素可以消费的。如果用的是if判断,那么被唤醒后就不会再次进行条件的判断,而是直接向下执行导致运行错误。我们的代码如下:
notify方法会唤醒等待一个对象锁的线程,但是具体唤醒哪个是不确定的。
2. 实现生产者消费者
如下使用if来判断会导致程序出错

一定要使用while来进行判断线程的等待条件而不是使用if
package thread.learn; import java.util.LinkedList;
import java.util.Queue;
import java.util.Random; /**
* Created by liujinhong on 2017/4/2.
* 生产者消费者问题是一个很经典的问题,值得好好研究一下
* java的wait和notify方法在使用时也是要非常注意的
*/
public class ProducerConsumer {
public static class Producer extends Thread {
Queue<Integer> queue;
int maxsize; Producer(Queue<Integer> queue, int maxsize, String name) {
this.queue = queue;
this.maxsize = maxsize;
this.setName(name);
}
@Override
public void run() {
while (true) {
synchronized (queue) {
try{
Thread.sleep(500);
} catch (Exception e) {} System.out.println(this.getName() + "获得队列的锁");
//条件的判断一定要使用while而不是if
if (queue.size() == maxsize) {
System.out.println("队列已满,生产者" + this.getName() + "等待");
try {
queue.wait();
} catch (Exception e) {}
}
int num = (int)(Math.random()*100);
queue.offer(num); System.out.println(this.getName() + "生产一个元素:" + num);
queue.notifyAll(); System.out.println(this.getName() + "退出一次生产过程!");
}
}
}
} public static class Consumer extends Thread {
Queue<Integer> queue;
int maxsize; Consumer(Queue<Integer> queue, int maxsize, String name) {
this.queue = queue;
this.maxsize = maxsize;
this.setName(name);
} @Override
public void run() {
while (true) {
synchronized (queue) {
try{
Thread.sleep(500);
} catch (Exception e) {} System.out.println(this.getName() + "获得队列的锁");
//条件的判断一定要使用while而不是if
if (queue.isEmpty()) {
System.out.println("队列为空,消费者" + this.getName() + "等待");
try{
queue.wait();
} catch (Exception e) {}
}
int num = queue.poll();
System.out.println(this.getName() + "消费一个元素:"+num);
queue.notifyAll(); System.out.println(this.getName() + "退出一次消费过程!");
}
}
}
} public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
int maxsize = 2; Producer producer = new Producer(queue, maxsize, "Producer");
Consumer consumer1 = new Consumer(queue, maxsize,"Consumer1");
Consumer consumer2 = new Consumer(queue, maxsize,"Consumer2");
Consumer consumer3 = new Consumer(queue, maxsize,"Consumer3"); producer.start();
consumer1.start();
consumer2.start();
consumer3.start();
}
}
Java中wait()和notify()方法的使用的更多相关文章
- Java中wait和sleep方法的区别
1.两者的区别 这两个方法来自不同的类分别是Thread和Object 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法(锁代码块和方法锁). wait ...
- 转 Java中wait和sleep方法的区别
1.两者的区别 这两个方法来自不同的类分别是Thread和Object 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法(锁代码块和方法锁). wait ...
- java中substring的使用方法
java中substring的使用方法 str=str.substring(int beginIndex);截取掉str从首字母起长度为beginIndex的字符串,将剩余字符串赋值给str: str ...
- Java中Set的contains()方法
Java中Set的contains()方法 -- hashCode与equals方法的约定及重写原则 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashCode() a ...
- [java,2017-05-16] java中清空StringBuffer的方法以及耗费时间比较
java中清空StringBuffer的方法,我能想到的有4种: 1. buffer.setLength(0); 设置长度为0 2. buffer.delete(0, buffer.length() ...
- java中BorderLayout的使用方法
相关设置: 使用BorderLayout布局上下左右中布局5个按键,单击中间的那个按键时就关闭窗口 代码: /**** *java中BorderLayout的使用方法 * 使用BorderLayout ...
- 【Java】Java中常用的String方法
本文转载于:java中常用的String方法 1 length()字符串的长度 String a = "Hello Word!"; System.out.println(a.len ...
- Java中Set的contains()方法——hashCode与equals方法的约定及重写原则
转自:http://blog.csdn.net/renfufei/article/details/14163329 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashC ...
- java中equals和hashCode方法随笔二
前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...
随机推荐
- MVC学习之HtmlHelper
1.为什么要使用HtmlHelper? 1.首先HtmlHelper是一个类型,MVC中的ViewPage<TModel>中的一个属性Html属性,这个属性的类型就是HtmlHelper& ...
- Token Based Authentication -- Implementation Demonstration
https://www.w3.org/2001/sw/Europe/events/foaf-galway/papers/fp/token_based_authentication/
- 设计模式之——Decorator模式
Decorator模式又叫装饰者模式,这种模式是为了满足Java开发的"面向扩展开放,面向修改闭源"的开发原则设计出来的. 在装饰者模式中,不修改源类的代码,却能修改源类中方法的功 ...
- 升级mac xcode打包证书报错 git 报错
reset tryAgain git 在钥匙串中找不到指定的项 重新配置公钥撕咬 SSH keys An SSH key allows you to establish a secure conne ...
- Feed系统架构资料收集(转)
add by zhj:有些链接已经失效,后续会修改. 原文:http://blog.csdn.net/zhangzhaokun/article/details/7834797 完全用nosql轻松打造 ...
- linux 下创建虚拟环境 python
virtualenv是一个可以在同一计算机中隔离多个python版本的工具.有时,两个不同的项目可能需要不同版本的python,如 python2.7 / python3.6 ,但是如果都装到一起,经 ...
- matplotlib-折线图、散点图
(一)折线图小结 1.设置图片大小(想要一个高清无码大图) # 图大小 plt.figure(figsize=(20, 8), dpi=80) 2.保存到本地 # 设置图片大小 plt.figure( ...
- linux创建新用户后shell无法自动补全命令或使用基本的shell命令
新建一用户lqding,切换到该用户下 root@lqding:~# su - lqding$$ echo $USERlqding$ ^[[A 提示符仅仅是一个$,很奇怪.输入命令,用TAB键也无法补 ...
- C++ Builder创建和调用dll中的资源
程序开发中经常会用到一些图标.图片.光标.声音等,我们称它们为资源(Resource).当多个窗口用到同样的资源时,可以将这些公共的资源放到一个dll文件里调用,这样,由于定位资源比在磁盘中定位文件花 ...
- 234. Palindrome Linked List(判断链表是否回文)
Given a singly linked list, determine if it is a palindrome. Follow up:Could you do it in O(n) time ...