通常,多线程之间需要协调工作。例如,浏览器的一个显示图片的线程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中的一个才有机会获得锁继续执行。
生产者:
package com.shejimoshi; import java.util.ArrayList; import java.util.List; /** * <p> * Title: 生产者 * </p> * * <p> * Description: * </p> * * <p> * Copyright: 融博技术有限公司 2013 * </p> * * @author 袁泉锋HO174959 * @version 1.0 * @date Mar 14, 2013 * */ public class Threada extends Thread { private List list; public Threada(List list){ this.list = list; } @Override public void run() { while (true) { synchronized (list) { if (list.size() > 4) { try { list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } list.add("1"); list.notify(); System.out.println("已经增加到:" + list.size()); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { List l = new ArrayList(); Threada a = new Threada(l); Threadb b = new Threadb(l); a.start(); b.start(); } }
消费者:
package com.shejimoshi; import java.util.List; /** * <p> * Title: 消费者 * </p> * * <p> * Description: * </p> * * <p> * Copyright: 融博技术有限公司 2013 * </p> * * @author 袁泉锋HO174959 * @version 1.0 * @date Mar 14, 2013 * */ public class Threadb extends Thread { private List list; public Threadb(List list){ this.list = list; } @Override public void run() { while (true) { synchronized (list) { if (list.size() == 0) { try { list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } list.remove(0); list.notify(); System.out.println("取了还剩下:" + list.size()); } try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
结果:
已经增加到:1 取了还剩下:0 已经增加到:1 取了还剩下:0 已经增加到:1 已经增加到:2 已经增加到:3 取了还剩下:2 已经增加到:3 取了还剩下:2 已经增加到:3 已经增加到:4 已经增加到:5 取了还剩下:4 已经增加到:5 取了还剩下:4 已经增加到:5 取了还剩下:4 已经增加到:5
相关推荐
wait方法可以让当前线程暂时放弃对象锁,让其他线程使用,而sleep和suspend方法不能做到这一点。 结论 在Java多线程编程中,wait和notify是两个非常重要的方法,它们用于线程之间的通信和同步。wait方法用于让当前...
`notify()`方法随机唤醒正在等待该对象锁的线程之一。被唤醒的线程将有机会重新获取锁并继续执行。然而,`notify()`并不保证被唤醒的线程会立即执行,因为线程调度取决于操作系统的线程调度策略。 #### `notifyAll...
需要注意的是,`wait()`、`notify()`和`notifyAll()`的调用者应当是持有对象锁的线程,否则会出现异常。此外,为了防止死锁和饥饿现象,合理地设计同步策略和唤醒逻辑至关重要。 总结来说,`wait`、`notify`和`...
在Java中,`wait()`、`notify()`和`notifyAll()`方法都是与对象锁相关的,它们用于控制线程的同步。使用这些方法的前提是线程必须拥有对象的监视器,也就是对象锁。这是通过在synchronized块或方法中调用它们来实现...
1. **wait()**:这个方法会让当前持有对象锁的线程进入等待状态,释放对象锁,让其他线程有机会获取锁。等待的线程必须在某个对象的监视器上等待,即在线程进入同步代码块或同步方法之前调用`wait()`。线程只有被...
`wait()` 方法会让当前持有锁的线程进入等待状态,释放锁,直到其他线程调用 `notify()` 或 `notifyAll()` 唤醒它。`notify()` 则会随机选择一个等待在该对象监视器上的线程并唤醒它,而 `notifyAll()` 则会唤醒所有...
3. **notifyAll()**:与`notify()`类似,但它会唤醒所有等待该对象的线程,这些线程都会尝试获取对象锁,最终只有一个成功并继续执行,其他线程仍然会在锁池中等待。 现在我们来看`sleep()`方法,它来自Thread类,...
当一个线程调用`notify()`时,会随机选择一个正在等待该对象锁的线程使其恢复运行。 - **`notify();`**:在`ThreadB`的`synchronized`代码块内,当累加操作完成后,调用`notify()`唤醒等待中的`ThreadA`线程,使得...
当一个线程执行到`wait()`方法时,它会释放当前持有的锁并进入等待状态,直到其他线程调用同一锁上的`notify()`或`notifyAll()`方法唤醒。`wait()`方法还有两个重载版本:`wait(long timeout)`和`wait(long timeout,...
wait()方法是使当前线程自动释放占有的对象锁,并等待notify。该方法的调用必须在synchronized代码块或者方法中,因为wait()方法需要当前线程必须获得对象锁。在wait()方法执行时,当前线程会释放当前的锁,然后让出...
在实际开发中,`wait()`、`notify()`和`synchronized`常常用于实现生产者消费者模型、读写锁等高级并发场景。通过理解并熟练掌握这些概念,开发者可以编写出更加高效、可靠的多线程程序。 在提供的压缩包文件`java_...
首先,`wait()`方法会导致当前线程进入等待状态,直到其他线程调用同一个对象的`notify()`或`notifyAll()`方法唤醒它。而`notify()`方法则会唤醒一个正在该对象上等待的线程,如果有多个线程在等待,哪个线程被唤醒...
在Java中,wait机制用于暂停当前线程的执行,并释放当前对象的锁,以便让其他线程获得锁并执行。在使用wait机制时,需要注意以下几点: * wait方法必须在synchronized块中调用,以确保线程安全。 * wait方法会释放...
与notify()类似,notifyAll()会唤醒所有等待该对象锁的线程。然而,这些线程仍然需要在获得锁后才能继续执行,这意味着只有一个线程能够在其他线程之前获取到锁并继续运行。 4. **Lock接口**: 为了解决`...
`wait()`方法的作用是使当前持有对象锁的线程暂停执行,进入等待池,释放对象锁,直到其他线程调用同一对象的`notify()`或`notifyAll()`方法来唤醒它。当线程被唤醒后,它并不会立即恢复执行,而是需要再次竞争对象...
wait方法的调用必须在synchronized块中进行,因为wait方法需要释放当前对象占有的锁。 notify方法: notify方法也是Object类中的一个方法,它用于唤醒当前对象上等待的线程。notify方法不会释放锁,因此在使用...
只有持有对象锁的线程才能调用`wait()`, `notify()`, `notifyAll()`。 **使用Wait-Notify机制时需要注意的事项:** 1. `wait()`, `notify()`, `notifyAll()`必须在`synchronized`代码块或方法中调用,以确保线程...
很多人会疑惑为什么必须持有这个对象的锁才能调用对象的wait()和notify()方法呢?其实这是因为wait()和notify()方法需要在synchronized块中使用,以确保线程安全。 在使用wait()和notify()方法时,需要注意以下几点...
- notify()方法会唤醒一个正在等待该对象锁的线程,但不保证是哪个线程,且唤醒的线程需要获取到锁才能继续执行。 - notifyAll()则会唤醒所有等待该对象锁的线程,这些线程都将进入锁的竞争队列。 3. **...