thread的wait\notify实现线程通信
来源:互联网 发布:人力资源公司源码 编辑:程序博客网 时间:2024/05/21 06:15
背景:
之前的文章介绍过wait与sleep的区别,本文从另一个角度梳理一种实现线程通信的方式。
正文:
wait()、notify()和notifyAll()是Object类中的方法:
1)wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。
2)调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁)
3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程;
4)调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程;
为何这三个不是Thread类声明中的方法,而是Object类中声明的方法(当然由于Thread类继承了Object类,所以Thread也可以调用者三个方法)?其实这个问题很简单,由于每个对象都拥有monitor(即锁),所以让当前线程等待某个对象的锁,当然应该通过这个对象来操作了。而不是用当前线程来操作,因为当前线程可能会等待多个线程的锁,如果通过线程来操作,就非常复杂了。package thread;public class NotifyTest { public static Object object = new Object(); public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread2 thread2 = new Thread2(); thread1.start(); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } thread2.start(); } static class Thread1 extends Thread{ @Override public void run() { synchronized (object) { try { object.wait(); } catch (InterruptedException e) { } System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁"); } } } static class Thread2 extends Thread{ @Override public void run() { synchronized (object) { object.notify(); System.out.println("线程"+Thread.currentThread().getName()+"调用了object.notify()");
<pre name="code" class="java"> <span style="white-space:pre"></span>System.out.println("线程"+Thread.currentThread().getName()+"释放了锁");} } }}运行结果如下:
当然wait还有几个重载的方法设置超时时间:
public final void wait(long timeout) throws InterruptedException;public final void wait(long timeout, int nanos) throws InterruptedException
导致线程进入等待状态直到它被通知或者经过指定的时间.
线面来看个常用的生产者消费者模式。模拟一个容器:
package thread;import java.util.LinkedList;public class Depository { int capability = 5; private static LinkedList<Product> pool = new LinkedList(); public LinkedList getPool() { return pool; } public synchronized int getSize() { return pool.size(); } public synchronized boolean isEmpty() { return pool.isEmpty(); } public synchronized boolean isFull() { if (this.getSize() == this.capability) { return true; } else { return false; } } public synchronized void addLast(Product p) { this.notifyAll(); if (!this.isFull()) { pool.addFirst(p); //System.out.println("当前线程的名称:" + Thread.currentThread().getName()); System.out.println(Thread.currentThread().getName() + " 放入一个产品"); System.out.println("仓库已经有 " + this.getSize() + " 个了"); } else { System.out.println("仓库满了,该线程" + Thread.currentThread().getName() + "等待"); try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} } } public synchronized Product remove(){ if(!this.isEmpty()){//不为空,取出 this.notifyAll(); // Product p=pool.removeFirst(); return p; }else{//等待 System.out.println("仓库空了,该线程" + Thread.currentThread().getName() + "等待"); try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} return null; } }}
package thread;public class Product {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public String toString(){return "product:"+this.name;}}
package thread;/** * * @author zhangliang * * 2016年4月8日 下午1:57:32 */public class PCTest {public static void main(String[] args) throws InterruptedException {// TODO Auto-generated method stubPCTest test = new PCTest();Depository pool = new Depository(); Producer pro=test.new Producer(pool); Consumer con=test.new Consumer(pool); Thread p = new Thread(pro); Thread c1 = new Thread(con); Thread c2 = new Thread(con); p.start(); c1.start(); c2.start(); Thread.sleep(500); p.interrupt(); c1.interrupt(); c2.interrupt(); }class Consumer implements Runnable{ //消费者线程拥有的资源 private Depository pool=null; //构造函数 public Consumer(Depository pool) { this.pool=pool; } volatile boolean flag=true; @Override public void run() { while(flag){ try { Thread.sleep(100); } catch (InterruptedException e) { flag =false; } Product p = this.pool.remove(); if(p!= null) { System.out.println("线程"+Thread.currentThread().getName()+"消费了"+p.toString()); } } }}//生产者线程class Producer implements Runnable{ //生产者线程拥有的资源 private Depository pool=null; //构造函数 public Producer(Depository pool) { this.pool=pool; } @Override public void run() { boolean flag=false; while(true) { if(!pool.isFull()) { Product p = new Product(); p.setName("p:"+System.currentTimeMillis()); this.pool.addLast(p); try {Thread.sleep(10);} catch (InterruptedException e) {flag =false;} } } }}}
运行结果如下:
Thread-0 放入一个产品仓库已经有 1 个了Thread-0 放入一个产品仓库已经有 2 个了Thread-0 放入一个产品仓库已经有 3 个了Thread-0 放入一个产品仓库已经有 4 个了Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150363Thread-0 放入一个产品仓库已经有 4 个了线程Thread-1消费了product:p:1460095150373Thread-0 放入一个产品仓库已经有 5 个了Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150443线程Thread-1消费了product:p:1460095150536Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150546Thread-0 放入一个产品线程Thread-1消费了product:p:1460095150433仓库已经有 4 个了Thread-0 放入一个产品仓库已经有 5 个了线程Thread-1消费了product:p:1460095150646Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150739Thread-0 放入一个产品仓库已经有 5 个了线程Thread-2消费了product:p:1460095150749线程Thread-1消费了product:p:1460095150636Thread-0 放入一个产品仓库已经有 4 个了Thread-0 放入一个产品仓库已经有 5 个了
1. 线程的等待或者唤醒,并不是让线程调用自己的wait或者notify方法,而是通过调用线程共享对象的wait或者notify方法来实现。
2. 线程要调用某个对象的wait或者notify方法,必须先取得该对象的监视器。
3. 线程的协作必须以线程的互斥为前提,这种协作实际上是一种互斥下的协作。
好了,本篇先到这里,下篇改用condition实现。
参考:
http://www.cnblogs.com/dolphin0520/p/3920385.html
0 0
- thread的wait\notify实现线程通信
- thread的wait\notify实现线程通信
- Thread:线程之间的通信,使用wait()和notify()
- wait()与notify()实现线程间的通信
- 用java来实现线程之间的wait、notify()通信
- wait和notify实现线程间的通信
- wait/notify/notifyAll实现线程间通信
- 使用wait/notify实现线程间通信
- wait 和 notify 实现线程间通信
- 线程通信notify(),wait()
- 线程-通信-wait/notify
- 线程通信,wait()与notify()的运用
- java的线程通信wait(),notify(),notifyAll()
- Java多线程通信-利用传统的线程通信wait(),notify()方法实现“生产者消费者模式”
- JavaSE 线程通信 wait() notify()
- 线程间通信 wait() notify()
- 线程之间通信 wait notify
- 线程通信---1.wait/notify
- Drozer – Android APP安全评估工具(附测试案例)
- 分享一个链接
- Linux join --根据关键字合并数据文件
- 项目需求的分析
- 批量sql语句
- thread的wait\notify实现线程通信
- 我的第一篇博客
- objective C中的@class, SEL , IMP等灵活机制
- 代码注入方式
- Linux kill --终止进程/发送信号
- linux中15个常用命令
- java 进制装换操作
- Linux killall --杀死指定名字的进程
- Spring编程式事务实现