使用wait()与notify()/notifyAll()可以使得多个任务之间彼 此协作。
1. wait()与notify()/notifyAll()
调用sleep()和yield()的时候锁并没有被释放,而调用wait() 将释放锁。这样另一个任务(线程)可以获得当前对象的锁,从而 进入它的synchronized方法中。可以通过notify()/notifyAll(), 或者时间到期,从wait()中恢复执行。
只能在同步控制方法或同步块中调用wait()、notify()和 notifyAll()。如果在非同步的方法里调用这些方法,在运行时会 抛出IllegalMoniTorStateException异常。
2.模拟单个线程对多个线程的唤醒
模拟线程之间的协作。Game类有2个同步方法prepare()和go() 。标志位start用于判断当前线程是否需要wait()。Game类的实例 首先启动所有的Athele类实例,使其进入wait()状态,在一段时间 后,改变标志位并notifyAll()所有处于wait状态的Athele线程。
Game.java
package concurrency;import java.util.Collection;import java.util.Collections;import java.util.HashSet;import java.util.IteraTor;import java.util.Set;class Athlete implements Runnable { private final int id; private Game game; public Athlete(int id, Game game) { this.id = id; this.game = game; } public boolean equals(Object o) { if (!(o instanceof Athlete)) return false; Athlete athlete = (Athlete) o; return id == athlete.id; } public String toString() { return "Athlete"; } public int hashCode() { return new Integer(id).hashCode(); } public void run() { try { game.prepare(this); } catch (InterruptedException e) { System.out.println(this + " quit the game"); } } }public class Game implements Runnable { private Set players = new HashSet(); private boolean start = false; public void addPlayer(Athlete one) { players.add(one); } public void removePlayer(Athlete one) { players.remove(one); } public Collection getPlayers() { return Collections.unmodifiableSet(players); } public void prepare(Athlete athlete) throws InterruptedException { System.out.println(athlete + " ready!"); synchronized (this) { while (!start) wait(); if (start) System.out.println(athlete + " go!"); } } public synchronized void go() { notifyAll(); } public void ready() { IteraTor iter = getPlayers ().iteraTor(); while (iter.hasNext()) new Thread(iter.next()).start(); } public void run() { start = false; System.out.println("Ready......"); System.out.println("Ready......"); System.out.println("Ready......"); ready(); start = true; System.out.println("Go!"); go(); } public static void main(String[] args) { Game game = new Game(); for (int i = 0; i < 10; i++) game.addPlayer(new Athlete(i, game)); new Thread(game).start(); }}
结果:
Ready......Ready......Ready......Athlete ready!Athlete ready!Athlete ready!Athlete ready!Athlete ready!Athlete ready!Athlete ready!Athlete ready!Athlete ready!Athlete ready!Go!Athlete go!Athlete go!Athlete go!Athlete go!Athlete go!Athlete go!Athlete go!Athlete go!Athlete go!Athlete go!
3.模拟忙等待过程
MyObject类的实例是被观察者,当观察事件发生时,它会通知 一个MoniTor类的实例(通知的方式是改变一个标志位)。而此 MoniTor类的实例是通过忙等待来不断的检查标志位是否变化。
BusyWaiting.java
<p “但行好事,莫问前程”,往往成功的几率反而更大些;