- 浏览: 700031 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (239)
- 系统架构设计 (16)
- java collection framework (2)
- java分布式 (4)
- java多线程 (0)
- 故障处理及调优 (16)
- 软件开发过程及管理 (28)
- OS (5)
- 常用算法 (3)
- design pattern (8)
- transaction (7)
- java apps (48)
- corejava (7)
- java and DB (10)
- cache (0)
- webservice (14)
- web前端 (25)
- 报表 (4)
- 日志系统设计 (3)
- Oracle (4)
- mysql (11)
- xml (11)
- 数据源配置管理 (3)
- 企业数据存储 (4)
- php (2)
- 测试 (1)
最新评论
-
orangebook:
对于初学者来说,这样编写可能会误导,理解更烦锁。
观察者模式(发布-订阅) -
liudajiang:
呵呵 startThreads(rand ...
实践缩小Java synchronized 粒度 -
zengwenbo5566:
谢谢博主,学习了
解决getOutputStream() has already been called for this response -
u011335423:
大神厉害啊 可以了
解决getOutputStream() has already been called for this response -
xiang37:
...
解决getOutputStream() has already been called for this response
wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。
这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。
•如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
•如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
•如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
其中wait方法有三个over load方法:
wait()
wait(long)
wait(long,int)
wait方法通过参数可以指定等待的时长。如果没有指定参数,默认一直等待直到被通知。
以下是一个演示代码,以最简洁的方式说明复杂的问题,简要说明下:
1.NotifyThread是用来模拟3秒钟后通知其他等待状态的线程的线程类;
2.WaitThread是用来模拟等待的线程类;
3.等待的中间对象是flag,一个String对象;
main方法中同时启动一个Notify线程和三个wait线程;
public class NotifyTest { private String flag = "true"; class NotifyThread extends Thread{ public NotifyThread(String name) { super(name); } public void run() { try { sleep(3000);//推迟3秒钟通知 } catch (InterruptedException e) { e.printStackTrace(); } flag = "false"; flag.notify(); } }; class WaitThread extends Thread { public WaitThread(String name) { super(name); } public void run() { while (flag!="false") { System.out.println(getName() + " begin waiting!"); long waitTime = System.currentTimeMillis(); try { flag.wait(); } catch (InterruptedException e) { e.printStackTrace(); } waitTime = System.currentTimeMillis() - waitTime; System.out.println("wait time :"+waitTime); } System.out.println(getName() + " end waiting!"); } } public static void main(String[] args) throws InterruptedException { System.out.println("Main Thread Run!"); NotifyTest test = new NotifyTest(); NotifyThread notifyThread =test.new NotifyThread("notify01"); WaitThread waitThread01 = test.new WaitThread("waiter01"); WaitThread waitThread02 = test.new WaitThread("waiter02"); WaitThread waitThread03 = test.new WaitThread("waiter03"); notifyThread.start(); waitThread01.start(); waitThread02.start(); waitThread03.start(); } }
OK,如果你拿这段程序去运行下的话, 会发现根本运行不了,what happened?满屏的java.lang.IllegalMonitorStateException。
没错,这段程序有很多问题,我们一个个来看。首先,这儿要非常注意的几个事实是:
1.任何一个时刻,对象的控制权(monitor)只能被一个线程拥有。
2.无论是执行对象的wait、notify还是notifyAll方法,必须保证当前运行的线程取得了该对象的控制权(monitor)
3.如果在没有控制权的线程里执行对象的以上三种方法,就会报java.lang.IllegalMonitorStateException异常。
4.JVM基于多线程,默认情况下不能保证运行时线程的时序性
基于以上几点事实,我们需要确保让线程拥有对象的控制权。也就是说在waitThread中执行wait方法时,要保证waitThread对flag有控制权;
在notifyThread中执行notify方法时,要保证notifyThread对flag有控制权。
线程取得控制权的方法有三:
1.执行对象的某个同步实例方法。
2.执行对象对应类的同步静态方法。
3.执行对该对象加同步锁的同步块。
我们用第三种方法来做说明:
将以上notify和wait方法包在同步块中
synchronized (flag) { flag = "false"; flag.notify(); } synchronized (flag) { while (flag!="false") { System.out.println(getName() + " begin waiting!"); long waitTime = System.currentTimeMillis(); try { flag.wait(); } catch (InterruptedException e) { e.printStackTrace(); } waitTime = System.currentTimeMillis() - waitTime; System.out.println("wait time :"+waitTime); } System.out.println(getName() + " end waiting!"); }
我们向前进了一步。问题解决了吗?
好像运行还是报错java.lang.IllegalMonitorStateException。what happened?
这时的异常是由于在针对flag对象同步块中,更改了flag对象的状态所导致的。如下:
flag="false";
flag.notify();
对在同步块中对flag进行了赋值操作,使得flag引用的对象改变,这时候再调用notify方法时,因为没有控制权所以抛出异常。我们可以改进一下,将flag改成一个JavaBean,然后更改它的属性不会影响到flag的引用。我们这里改成数组来试试,也可以达到同样的效果:
private String flag[] = {"true"}; synchronized (flag) { flag[0] = "false"; flag.notify(); } synchronized (flag) { flag[0] = "false"; flag.notify(); } synchronized (flag) { while (flag[0]!="false") { System.out.println(getName() + " begin waiting!"); long waitTime = System.currentTimeMillis(); try { flag.wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
这时候再运行,不再报异常,但是线程没有结束是吧,没错,还有线程堵塞,处于wait状态。原因很简单,我们有三个wait线程,只有一个notify线程,notify线程运行notify方法的时候,是随机通知一个正在等待的线程,所以,现在应该还有两个线程在waiting。我们只需要将NotifyThread线程类中的flag.notify()方法改成notifyAll()就可以了。notifyAll方法会通知所有正在等待对象控制权的线程。 最终完成版如下:
public class NotifyTest { private String flag[] = { "true" }; class NotifyThread extends Thread { public NotifyThread(String name) { super(name); } public void run() { try { sleep(3000);// 推迟3秒钟通知 } catch (InterruptedException e) { e.printStackTrace(); } synchronized (flag) { flag[0] = "false"; flag.notifyAll(); } } }; class WaitThread extends Thread { public WaitThread(String name) { super(name); } public void run() { synchronized (flag) { while (flag[0] != "false") { System.out.println(getName() + " begin waiting!"); long waitTime = System.currentTimeMillis(); try { flag.wait(); } catch (InterruptedException e) { e.printStackTrace(); } waitTime = System.currentTimeMillis() - waitTime; System.out.println("wait time :" + waitTime); } System.out.println(getName() + " end waiting!"); } } } public static void main(String[] args) throws InterruptedException { System.out.println("Main Thread Run!"); NotifyTest test = new NotifyTest(); NotifyThread notifyThread = test.new NotifyThread("notify01"); WaitThread waitThread01 = test.new WaitThread("waiter01"); WaitThread waitThread02 = test.new WaitThread("waiter02"); WaitThread waitThread03 = test.new WaitThread("waiter03"); notifyThread.start(); waitThread01.start(); waitThread02.start(); waitThread03.start(); } }
发表评论
-
Http状态码及实例
2018-03-24 15:06 0HTTP常用状态码列表: ... -
java同步机制及synchronized关键字的应用2
2013-03-25 22:03 1556类定义: public class Test{ ... -
实践缩小Java synchronized 粒度
2013-03-07 22:09 2126项目需求: 产品需要监视不同种类的多个数据库,例如:多个 ... -
java同步机制及synchronized关键字的应用1
2013-03-05 23:04 993Java对多线程的支持与同步机制深受大家的喜爱,通过JMM ... -
Thread_管理异步、定时及周期性任务
2012-09-24 14:43 1301项目中有很多异步、定时及周期性任务的需求,其实现有一定的特点, ... -
Thread_跨节点集合查询
2012-09-18 16:56 1673项目中数据库进行了水平切分,为了处理跨节点集合查询,采用了多线 ... -
Thread_大批量数据的分页处理(生产者-消费者)
2012-09-17 13:30 1406java应用中通常会有处理大批量数据的场景,这里介绍一种分 ... -
计算java对象占用的内存
2011-12-13 11:38 1074Java有一个很好的地方就是java的垃圾收集机制,这个机制集 ... -
java调用shell执行数据压缩
2011-07-18 17:44 1495项目需求: 将迁移来的数据文件进行压缩。要求压缩过程耗时尽量 ... -
quartz应用之一:创建、关闭定时任务
2011-07-18 17:15 3490项目需求: 数据迁移进程开始执行后,启动定时任务每隔30秒计 ... -
xtree应用实例
2011-03-11 18:02 1377最近项目中用到了构造树形目录的功能,简单了解了下dtree和x ... -
JDBC方式访问数据库
2011-01-10 13:48 14331、 JDBC是什么JDBC是Java数据库连接(Java ... -
应用系统中配置文件的应用场景及简要分析
2010-11-12 16:13 1216使用配置文件的有点不外乎两点: 1.提高系统的灵活性。 2 ... -
解决getOutputStream() has already been called for this response
2010-08-26 14:57 158643getOutputStream() has already b ... -
实战防止重复提交(token)应用思路及过程
2010-06-11 16:39 1622我这里只考虑了直接使用struts API的情况,使用自定义的 ... -
Struts国际化完整解决方案-支持多国语言
2010-06-11 16:38 2074在网上有很多有关Struts的中文解决方案,但是很多都说得很零 ... -
jsp查询条件的保留
2010-06-11 16:23 2795本文适合java web开发初学者参考。 统计系统或者 ... -
java日期计算
2010-05-26 14:45 1341Calendar类:一个抽像类,不能直接new 得到。 Cal ... -
mvc应用实例
2010-04-04 19:58 998最近参与到一个行业数据处理的项目,我负责数据请求和订阅的功能, ... -
反斜杠处理
2009-12-16 10:03 1261在Java中处理一些路径相关的问题的时候,如要取出ie浏览器上 ...
相关推荐
### 使用wait和notifyAll方法详解 #### 一、引言 在Java多线程编程中,`wait()` 和 `notifyAll()` 方法是非常重要的同步机制,主要用于实现线程间的通信与同步控制。通过合理运用这些方法,可以有效地解决生产者...
Java 中Object的wait() notify() notifyAll()方法使用 在Java并发编程中,Object的wait()、notify()和...wait()、notify()和notifyAll()方法是Java并发编程中非常重要的概念,理解它们的使用方法和价值是非常重要的。
当一个线程执行到`wait()`方法时,它会释放当前持有的锁并进入等待状态,直到其他线程调用同一锁上的`notify()`或`notifyAll()`方法唤醒。`wait()`方法还有两个重载版本:`wait(long timeout)`和`wait(long timeout,...
`wait()` 方法会让当前持有锁的线程进入等待状态,释放锁,直到其他线程调用 `notify()` 或 `notifyAll()` 唤醒它。`notify()` 则会随机选择一个等待在该对象监视器上的线程并唤醒它,而 `notifyAll()` 则会唤醒所有...
no2_wait_notify wait-notify-notifyAll的实例 no3_thread_hangup 线程挂起的几种实现方式 no4_join join的实例 no5_thread_stop 停止线程的几种方法 no6_deadlock 模拟死锁 no7_threadlocal ThreadLocal...
文章目录1 wait、notify、notifyAll简单介绍1.1 使用方法 + 为什么不是Thread类的方法1.2 什么时候加锁、什么时候释放锁?1.3 notify、notifyAll的区别2 两个比较经典的使用案例2.1 案例1 — ABCABC。。。三个线程...
本文将深入探讨`wait`、`notify`以及`notifyAll`这三个关键字的使用及其背后的原理,帮助你理解如何在实际编程中有效地利用它们来解决线程同步问题。 首先,我们需要了解Java中的对象锁。每个Java对象都有一个内置...
1. **wait()**:当一个线程调用对象的`wait()`方法时,它会释放当前对象的锁,并进入等待池,直到其他线程调用同一对象的`notify()`或`notifyAll()`方法唤醒它。唤醒后,线程不会立即恢复执行,而是需要重新获取对象...
本文旨在解析一个具体的Java多线程示例代码,以帮助读者更好地理解`wait()`与`notify()`方法的作用及其实现机制。这两个方法是Java中实现线程间通信的重要手段之一,尤其在解决生产者消费者模型、读者写者问题等经典...
`wait()` 方法用于使当前线程进入等待状态,直到其他线程调用该对象的 `notify()` 或 `notifyAll()` 方法来唤醒它。当调用 `wait()` 方法时,当前线程会释放锁,并等待其他线程唤醒。`wait()` 方法通常在一个循环中...
wait() 方法可以通过 notify 或者 notifyAll 或者指定睡眠时间来唤醒当前等待池中的线程。 sleep() 和 wait() 方法的区别 sleep() 和 wait() 方法的最大区别是: 1. sleep() 睡眠时,保持对象锁,仍然占有该锁; ...
Java多线程编程中,`wait()`, `notify()`, 和 `notifyAll()` 是三个非常重要的方法,它们用于线程间通信和同步。这些方法并不是定义在 `Thread` 类中的,而是作为 `Object` 类的一部分,这意味着任何Java对象都可以...
当一个线程调用wait()方法时,它会释放持有锁并进入等待状态,直到其他线程调用同一对象的notify()或notifyAll()方法唤醒它。 3. **条件变量(Condition)**:在Java并发包java.util.concurrent.locks中,条件变量...
在给定的代码示例中,我们看到了一个模拟家庭共享同一银行账户的场景,通过使用Java多线程的wait()和notify()方法来控制不同线程(代表家庭成员)的操作顺序。这里涉及到的关键知识点包括: 1. **Java多线程**:...
Java提供了wait(), notify()和notifyAll()方法,这些方法需要在synchronized块或方法中调用,用于在线程间交换信息。另外,还有java.util.concurrent包下的BlockingQueue,它可以作为线程间的生产者-消费者模型,...
`wait()`方法的作用是使当前持有对象锁的线程暂停执行,进入等待池,释放对象锁,直到其他线程调用同一对象的`notify()`或`notifyAll()`方法来唤醒它。当线程被唤醒后,它并不会立即恢复执行,而是需要再次竞争对象...
10. HashMap什么样的类适合作为键String最为常见,因为String对象不可变,且重写了equals和hashcode方法。...sleep可在任意地方使用,wait notify notifyAll只能在synchronized块\方法中使用。sleep必须捕获异常
在Java中,`wait()`, `notify()`, `notifyAll()`方法是`Object`类的成员,而不是`Thread`类的,这意味着任何对象都可以作为等待和通知的基础。 **1. 状态变量(State Variable)** 状态变量是线程间通信的关键。当...
- **wait(), notify()和notifyAll()**:这些方法在Object类中定义,用于线程间通信,必须在同步块或同步方法中使用。 - **生产者-消费者模型**:使用BlockingQueue实现线程间的数据交换,避免死锁。 - **哲学家...
- `wait()`, `notify()`, `notifyAll()`:这些方法在`Object`类中,用于线程间的协作。一个线程调用`wait()`会释放同步锁并等待,而其他线程可以通过`notify()`或`notifyAll()`唤醒等待的线程。 - `join()`: 使当前...