`
xiaobian
  • 浏览: 588179 次
  • 来自: 北京
社区版块
存档分类
最新评论

Java Gossip: wait()、notify()

阅读更多
http://caterpillar.onlyfun.net/GossipCN/JavaGossip-V2/WaitNotify.htm


wait()、notify()与notifyAll()是由 Object所提供的方法,您在定义自己的类别时会继承下来(记得Java中所有的物件最顶层都继承自Object),wait()、notify()与 notifyAll()都被宣告为"final",所以您无法重新定义它们,透过这三个方法您可以控制执行绪是否为Runnable状态。

您必须在同步化的方法或区块中呼叫wait()方法,当物件的wait()方法被调用,目前的执行绪会被放入物件的“等待集合”(Wait set)中,执行绪会释放物件的锁定,其它的执行绪可以竞争锁定,取得锁定的执行绪可以执行同步化区块;被放在等待集中的执行绪将不参与执行绪的排班,wait()可以指定等待的时间,如果指定时间的话,则时间到之后执行绪会再度加入排班,如果指定时间0或不指定,则执行绪会持续等待,直到有被中断(interrupt)或是被告知(notify)可以参与排班。

当物件的notify()被调用,它会从物件的等待集中选出“一个”执行绪加入排班,被选出的执行绪是随机的,被选出的执行绪会与其它正在执行的执行绪共同竞争对物件的锁定;如果您呼叫notifyAll(),则“所有”在等待集中的执行绪都会被唤醒,这些执行绪会与其它正在执行的执行绪共同竞争对物件的锁定。

简单的说,当执行绪呼叫到物件的wait()方法时,表示它要先让出物件的被同步区使用权并等待通知,或是等待一段指定的时间,直到被通知或时间到时再从等待点开始执行,这就好比您要叫某人作事,作到一半时某人叫您等候通知(或等候1分钟之类的),当您被通知(或时间到时)某人会继承为您服务。

说明wait()、notify()或notifyAll()的应用最常见的一个例子,就是生产者(Producer)与消费者(Consumer)的例子,如果生产者会将产品交给店员,而消费者从店员处取走产品,店员一次只能持有固定数量产品,如果生产者生产了过多的产品,店员叫生产者等一下(wait),如果店中有空位放产品了再通知(notify)生产者继续生产,如果店中没有产品了,店员会告诉消费者等一下(wait),如果店中有产品了再通知(notify)消费者来取走产品。


以下举一个最简单的:生产者每次生产一个int整数交给在店员上,而消费者从店员处取走整数,店员一次只能持有一个整数。

以程式实例来看,首先是生产者: 

Producer.java 
package onlyfun.caterpillar; public class Producer implements Runnable {    private Clerk clerk;         public Producer(Clerk clerk) {         this.clerk = clerk;     }         public void run() {         System.out.println(                "生产者开始生产整数......");         // 生产1到10的整数        for(int product = 1; product <= 10; product++) {             try {                 // 暂停随机时间                Thread.sleep((int) (Math.random() * 3000));             }             catch(InterruptedException e) {                 e.printStackTrace();             }             // 将产品交给店员            clerk.setProduct(product);         }           } } 

再来是消费者:

Consumer.java 
package onlyfun.caterpillar; public class Consumer implements Runnable {    private Clerk clerk;         public Consumer(Clerk clerk) {         this.clerk = clerk;     }         public void run() {         System.out.println(                "消费者开始消耗整数......");         // 消耗10个整数        for(int i = 1; i <= 10; i++) {             try {                 // 等待随机时间                Thread.sleep((int) (Math.random() * 3000));             }             catch(InterruptedException e) {                 e.printStackTrace();             }             // 从店员处取走整数            clerk.getProduct();         }     }  } 

生产者将产品放至店员,而消费者从店员处取走产品,所以店员来决定谁必须等待并等候通知。

Clerk.java 
package onlyfun.caterpillar; public class Clerk {    // -1 表示目前没有产品    private int product = -1;      // 这个方法由生产者呼叫    public synchronized void setProduct(int product) {         if(this.product != -1) {             try {                 // 目前店员没有空间收产品,请稍候!                wait();             }             catch(InterruptedException e) {                 e.printStackTrace();             }         }          this.product = product;         System.out.printf("生产者设定 (%d)%n", this.product);         // 通知等待区中的一个消费者可以继续工作了        notify();     }         // 这个方法由消费者呼叫    public synchronized int getProduct() {         if(this.product == -1) {             try {                 // 缺货了,请稍候!                wait();             }             catch(InterruptedException e) {                 e.printStackTrace();             }         }          int p = this.product;         System.out.printf(                  "消费者取走 (%d)%n", this.product);         this.product = -1;          // 通知等待区中的一个生产者可以继续工作了        notify();                return p;     } } 

使用这么一个程式来测试:

WaitNotifyDemo.java 
package onlyfun.caterpillar; public class WaitNotifyDemo {    public static void main(String[] args) {        Clerk clerk = new Clerk();          Thread producerThread = new Thread(                new Producer(clerk));         Thread consumerThread = new Thread(                new Consumer(clerk));          producerThread.start();         consumerThread.start();     }} 

执行结果:
 生产者开始生产整数......
消费者开始消耗整数......
生产者设定 (1)
消费者取走 (1)
生产者设定 (2)
消费者取走 (2)
生产者设定 (3)
消费者取走 (3)
生产者设定 (4)
消费者取走 (4)
生产者设定 (5)
消费者取走 (5)
生产者设定 (6)
消费者取走 (6)
生产者设定 (7)
消费者取走 (7)
生产者设定 (8)
消费者取走 (8)
生产者设定 (9)
消费者取走 (9)
生产者设定 (10)
消费者取走 (10)
 

生产者会生产10个整数,而消费者会消耗10个整数,由于店员处只能放置一个整数,所以每生产一个就消耗一个,其结果如上所示是无误的。

如果一个执行绪进入物件的等待集中,您可以中断它的等待,这时将会发生InterruptedException例外物件,interrupt()方法可用来进行这项工作。
分享到:
评论

相关推荐

    Java经典问题算法大全

    2.Algorithm Gossip: 费式数列. 3. 巴斯卡三角形 4.Algorithm Gossip: 三色棋 5.Algorithm Gossip: 老鼠走迷官(一) 6.Algorithm Gossip: 老鼠走迷官(二) 7.Algorithm Gossip: 骑士走棋盘 8.Algorithm Gossip: 八...

    经典算法大全.pdf

    巴斯卡三角形 6 4.Algorithm Gossip: 三色棋 7 5.Algorithm Gossip: 老鼠走迷官(一) 9 6.Algorithm Gossip: 老鼠走迷官(二) 11 7.Algorithm Gossip: 骑士走棋盘 13 8.Algorithm Gossip: 八皇后 ...

    Java Gossip(一)

    1. **基础语法**:Java的基础语法包括变量声明、数据类型(如整型、浮点型、字符型和布尔型)、运算符(算术、比较、逻辑和位运算符)、流程控制(if语句、switch语句、for循环、while循环和do-while循环)以及数组...

    经典算法大全

    2.Algorithm Gossip: 费式数列 5 3. 巴斯卡三角形 6 4.Algorithm Gossip: 三色棋 7 5.Algorithm Gossip: 老鼠走迷官(一) 9 6.Algorithm Gossip: 老鼠走迷官(二) 11 7.Algorithm Gossip: 骑士走棋盘 ...

    Java Gossip(二)

    1. 类与对象:Java是一种面向对象的语言,一切皆为对象。在这个阶段,我们将深入了解类的定义,包括属性(成员变量)和方法(成员函数)。同时,会学习如何通过构造器初始化对象,并理解类与对象的关系。 2. 继承:...

    Java Gossip

    Java Gossip是一个专门为初学者设计的Java学习教程,它通过简洁易懂的语言深入浅出地讲解了Java编程的基础知识。这个教程旨在帮助新手快速掌握Java编程语言的核心概念,从而能够开始编写自己的Java程序。 首先,...

    R-gossip:分布式负载均衡效率优化算法.pdf

    R-gossip算法通过在分布式系统的集群代理节点上设置移位寄存器,优化了传统gossip算法的收敛速度和负载均衡效率。这一改进为分布式系统提供了一种有效的负载均衡优化方案,对分布式系统设计和性能优化具有重要的指导...

    Algorithm.rar_Algorithm Gossip_gossip_gossip algorithm_gossip算法

    2.Algorithm Gossip: 费式数列 3. 巴斯卡三角形 4.Algorithm Gossip: 三色棋 5.Algorithm Gossip: 老鼠走迷官 6.Algorithm Gossip: 老鼠走迷官(二) 7.Algorithm Gossip: 骑士走棋盘 8.Algorithm Gossip: 八皇 9....

    camel-gossip:骆驼八卦

    草稿用法: from("gossip://&lt;bound&gt;:&lt;port&gt;/?peers=&lt;listOfPeers&gt;&routeIds=&lt;listOfRouteIdsToControl&gt;").to("controlbus:route");listOfRouteIdsToControl在此节点被提升/降级时启动/停止。 当您在需要故障转移...

    99乘法表java源码-gossip:一个javalisp解析器

    99乘法表java源码 gossip - yet another lisp interpreter gossip是一个lisp解释器, 语法借鉴了scheme以及common lisp, 此项目的主要目的是学习。 安装 下载源码 打包: mvn package 运行方式: java -jar your_gossip...

    AlgorithmGossip 常用算法C/java实现

    AlgorithmGossip是一个非常有价值的资源集合,它包含了众多常用算法的C和Java实现。这个压缩包旨在为学习者和开发者提供一个实践和理解算法的平台,无论是初学者还是经验丰富的程序员,都能从中受益。 首先,我们要...

    一个 Java 版的 Gossip 协议实现.rar

    一个 Java 版的 Gossip 协议实现。 Gossip 算法又被称为反熵(Anti-Entropy),熵是物理学上的一个概念,代表杂乱无章,而反熵就是在杂乱无章中寻求一致,这充分说明了 Gossip 的特点:在一个有界网络中,每个节点...

    java源码:第三代的P2P网络 ANts P2P.zip

    ANts P2P可能会采用Gossip协议或者其他的复制策略来保证节点间数据的一致性。 6. **并发和多线程**:P2P网络通常需要处理大量并发请求,因此ANts P2P的源码中会涉及到线程池、并发控制(如锁和条件变量)以及异步...

    java源码:分布式缓存框架 SwarmCache.zip

    源码中,你可以看到如何使用JGroups进行节点间的通信,以及如何实现分布式缓存的数据一致性算法,如Gossip协议或Paxos协议。 `commons-logging.jar`是Apache Commons Logging库,它提供了一个抽象层,允许在不修改...

    gossip:Gossip协议的Go实现

    Gossip协议的Go实现。 概述 该软件包提供了最终一致的内存中数据存储的实现。 数据存储值使用推挽式八卦协议进行交换。 // Create a gossiper g := NewGossiper("&lt;ip&gt;:&lt;port&gt;", "&lt;unique&gt;", "&lt;peer&gt;") // Add ...

    良葛格 Java 学习笔记-JavaGossip全(v1+v2)

    6. **多线程**:讨论并发编程的基础,线程的创建与同步,包括synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和ReentrantLock等高级并发工具。 7. **网络编程**:涵盖Socket编程,TCP和UDP的...

    R-gossip:分布式负载均衡效率优化算法

    针对在分布式一致性系统中常用的gossip算法负载均衡效率较低的问题,本文在概率gossip算法(probabilistic gossip algorithm)的基础上,设计了一种寄存器gossip算法(register gossip algorithm,下文简称R-gossip...

    Java Gossip V2

    1. **多线程与并发**:Java是多线程编程的首选语言之一。教程可能会讲解线程的创建、同步机制(如synchronized关键字,Lock接口),以及并发工具类(如Semaphore、CountDownLatch、CyclicBarrier等)的使用。 2. **...

    CSC-582-3-W15-GOSSIP:分布式八卦算法

    分布式八卦算法,通常被称为Gossip协议,是一种在分布式系统中高效传播和同步信息的方法...通过阅读和分析这些代码,可以深入理解Gossip协议在Java中的具体应用和实现细节,这对于学习和设计分布式系统是非常有价值的。

Global site tag (gtag.js) - Google Analytics