转载自:http://sishuok.com/forum/blogPost/list/3674.html
通常,多线程之间需要协调工作。例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕。如果图片还没有下载完,displayThread可以暂停,当downloadThread完成了任务 后,再通知displayThread“图片准备完毕,可以显示了”,这时,displayThread继续执行。
以上逻辑简单的说就是:如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify。等待机制与锁机制是密切关联的。例如:
synchronized(obj) {while(!condition) {obj.wait();}obj.doSomething();}
当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。
在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:
synchronized(obj) {condition = true;obj.notify();}
需要注意的概念是:
◆调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {...} 代码段内。
◆调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {...} 代码段内唤醒A。
◆当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。
◆如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。
◆obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。
◆当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行
public class TestWaitNotify { // 锁 Byte lock = 0; // 条件,当条件为真,AThread才能往下执行,否则会等待,直到有线程将条件改为真。 Boolean condition = false; //内部类:等待线程 class AThread extends Thread { public void methodA() { if (condition) { System.out.println("方法methodA执行"); } else { try { /* * 这里要特别注意, * (1)只能在同步控制方法或同步块中调用wait()、notify()和notifyAll()。如果在非同步的方法里调用这些方法,在运行时会抛出IllegalMonitorStateException异常。 * (2)synchronized的锁与notity的调用对象必须一致,否则也会抛出IllegalMonitorStateException异常; * (3)下面的代码也会使抛出异常: * synchronized(condtion){condition=true;condition.wait(); * 因为condition改变以后,synchronized中的对象与调用wait方法的对象已经不同。 * 所以condtion与lock要分开,因为condtion会改变 * */ synchronized (lock) { System.out.println("方法methodA等待"); lock.wait(); System.out.println("方法methodA等待结束"); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void run() { methodA(); } } //内部类 notify线程 class BThread extends Thread { @Override public void run() { synchronized (lock) { System.out.println("方法methodB执行"); condition = true; lock.notifyAll(); System.out.println("方法methodB唤醒"); } } } public static void main(String[] args) { TestWaitNotify t = new TestWaitNotify(); TestWaitNotify.AThread aThread = t.new AThread(); aThread.start(); TestWaitNotify.BThread bThread = t.new BThread(); bThread.start(); } }
相关推荐
backport-util-concurrent.jarbackport-util-concurrent.jarbackport-util-concurrent.jar
《深入解析Atlassian Util Concurrent库:0.0.12版本》 在IT行业中,高效且可靠的并发处理是系统性能优化的关键因素之一。Atlassian公司,以其强大的协作工具如Jira、Confluence等闻名,也提供了许多开源工具来支持...
$ npm install --save-dev grunt-concurrent 用法 require ( 'load-grunt-tasks' ) ( grunt ) ; grunt . initConfig ( { concurrent : { target1 : [ 'coffee' , 'sass' ] , target2 : [ 'jshint' , 'mocha' ] ...
《mulle-concurrent:构建无锁且无等待的哈希表与数组》 在软件开发中,尤其是在多线程环境中,数据结构的选择对于程序性能和并发性至关重要。`mulle-concurrent`是一个专注于并发编程的C语言库,其中的`:antenna_...
concurrent.jar 里面有,使用Apache JCS 时候需要的EDU/oswego/cs/dl/util/concurrent/Channel ,编译 jcaptcha时候需要第EDU.oswego.cs.dl.util.concurrent.ClockDaemon类, concurrent-1.3.3.jar
标题"Concurrent:用于展示竞争名单"可能是在指一个项目或示例,旨在演示如何在并发环境中处理竞争条件。竞争条件发生在多个线程同时访问和修改共享数据时,可能导致数据不一致。Java通过锁机制(如`synchronized`...
本资源“concurrent:java并发编程的示例和原始代码分析”提供了深入理解和实践Java并发特性的宝贵材料。以下是对该资源中可能包含的知识点的详细说明: 1. **Java并发API**: 这个资源可能涵盖了Java的并发库,包括`...
标题中的"backport-util-concurrent-3.1.jar"和"geronimo-stax-api_1.0_spec-1.0.1.jar"是两个Java库文件,它们在解决Eclipse Axis2 Codegen插件报错问题时起着关键作用。Axis2是一个流行的Web服务框架,而Codegen...
首先,Java中的`java.util.concurrent`包是进行并发编程的核心库,包含了线程池、并发集合、锁机制等关键组件。线程池如`ExecutorService`和`ThreadPoolExecutor`,通过复用线程来提高性能,避免频繁创建和销毁线程...
Java的`wait()`、`notify()`和`notifyAll()`方法用于线程间的通信,但它们必须在同步块或同步方法中使用,以防止死锁和其他并发问题。 9. **并发设计模式** 了解如生产者消费者模型、读者写者模式、双检锁/双重...
本文将深入探讨Java中的wait()、notify()和notifyAll()方法,以及synchronized关键字和原子操作在多线程环境中的应用。 1. **wait()方法**: - wait()是Object类的一个方法,它的作用是让当前线程暂停执行并释放它...
本资源“concurrent:Java并发,源可用于android和java进行并发”提供了用于Android和Java平台的并发编程的相关源码,这对于我们深入理解和实践并发编程具有很高的价值。 首先,我们要理解Java中的并发基础。Java...
- **wait()** 和 **notify()**:基于对象监视器的线程通信方式,用于线程间的协作。 - **Phaser**:一种灵活的线程同步机制,可进行多阶段的同步。 6. **并发设计模式** - **生产者-消费者模式**:通过队列进行...
在版本,工件已重命名:新名称: < dependency> < groupId>net.tascalate</ groupId> < artifactId>net.tascalate.concurrent</ artifactId> < version>0.9.5</ version> <!-- Any version above 0.8.0, the ...
开始从原始二进制研究Concurrent包,以及其他并发相关的包,对于途中遇到的不明白的东西,也会作相应了解。 该项目的缘由是看CopyOnWriteArrayList二进制时,对Unsafe类一无所知,才有了好钻钻一番的冲动。 ...
`java-concurrent`通常指的是Java的并发包`java.util.concurrent`,这个包提供了大量的类和接口,帮助开发者有效地管理和控制并发操作。下面我们将深入探讨这个主题。 首先,`java.util.concurrent`包中的核心组件...
安装将此存储$HOME/.manuel.d/plugins到您的 manuel 插件目录(默认$HOME/.manuel.d/plugins ): $ cd ~ /.manuel.d/plugins$ git clone git://github.com/ShaneKilkelly/manuel-contrib-concurrent.git用法只需将...
io.github.hank.java.concurrent.n2 - 同步与异步 io.github.hank.java.concurrent.n3 - Java线程 io.github.hank.java.concurrent.n4 - 共享模型之管程 io.github.hank.java.concurrent.n5 - 共享模型之内存 io....
Java `concurrent` 包是Java提供的一个核心库,它为并发编程提供了丰富的工具和类,帮助开发者编写更加高效和线程安全的代码。本资源——`java_concurrent` 源码,提供了对Java并发包的深入学习材料以及实践示例,...
在这个名为"imgr-concurrent"的项目中,我们看到的是一个与图像处理相关的JavaScript库的测试用例,特别是针对并发操作的。 "imgr"可能是一个JavaScript库,专门设计用于高效地处理图像,比如缩放、裁剪、转换格式...