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

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 学习笔记-JavaGossip全(v1+v2)

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

    JavaGossip-V2.zip_TEACH

    线程同步和通信机制如synchronized关键字、wait()和notify()方法也是重点。 9. **接口与抽象类**:接口作为完全抽象的契约,用于定义行为规范;抽象类则作为部分抽象的基类,可包含具体实现。两者都是实现多继承的...

    避开10大常见坑:DeepSeekAPI集成中的错误处理与调试指南.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    前端分析-2023071100789

    前端分析-2023071100789

    基于kinect的3D人体建模C++完整代码.cpp

    基于kinect的3D人体建模C++完整代码.cpp

    搞机工具箱10.1.0.7z

    搞机工具箱10.1.0.7z

    GRU+informer时间序列预测(Python完整源码和数据)

    GRU+informer时间序列预测(Python完整源码和数据),python代码,pytorch架构,适合各种时间序列直接预测。 适合小白,注释清楚,都能看懂。功能如下: 代码基于数据集划分为训练集测试集。 1.多变量输入,单变量输出/可改多输出 2.多时间步预测,单时间步预测 3.评价指标:R方 RMSE MAE MAPE,对比图 4.数据从excel/csv文件中读取,直接替换即可。 5.结果保存到文本中,可以后续处理。 代码带数据,注释清晰,直接一键运行即可,适合新手小白。

    性价比革命:DeepSeekAPI成本仅为GPT-4的3%的技术揭秘.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水

    基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水模拟dem-sph-fem耦合 ,基于ANSYS LSDyna; 滑坡入水模拟; DEM-SPH-FEM 耦合,基于DEM-SPH-FEM耦合的ANSYS LSDyna滑坡入水模拟

    auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

    auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

    复件 复件 建设工程可行性研究合同[示范文本].doc

    复件 复件 建设工程可行性研究合同[示范文本].doc

    13考试真题最近的t64.txt

    13考试真题最近的t64.txt

    Microsoft Visual C++ 2005 SP1 Redistributable PackageX86

    好用我已经解决报错问题

    嵌入式开发入门:用C语言点亮LED灯的全栈开发指南.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    auto_gptq-0.4.2-cp38-cp38-win_amd64.whl

    auto_gptq-0.4.2-cp38-cp38-win_amd64.whl

    自动立体库设计方案.pptx

    自动立体库设计方案.pptx

    手把手教你用C语言实现贪吃蛇游戏:从算法设计到图形渲染.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    性能对决:DeepSeek-V3与ChatGPTAPI在数学推理场景的基准测试.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    从零到一:手把手教你用Python调用DeepSeekAPI的完整指南.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    为什么你的switch总出bug?90%新手不知道的break语句隐藏规则.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

Global site tag (gtag.js) - Google Analytics