天天看点

Java:使用wait()与notify()实现线程间协作

使用wait()与notify()/notifyAll()可以使得多个任务之间彼此协作。

<b>1. wait()</b><b>与</b><b>notify()/notifyAll()</b>

<b></b>

调用sleep()和yield()的时候锁并没有被释放,而调用wait()将释放锁。这样另一个任务(线程)可以获得当前对象的锁,从而进入它的synchronized方法中。可以通过notify()/notifyAll(),或者时间到期,从wait()中恢复执行。

只能在同步控制方法或同步块中调用wait()、notify()和notifyAll()。如果在非同步的方法里调用这些方法,在运行时会抛出IllegalMonitorStateException异常。

<b>2.</b><b>模拟单个线程对多个线程的唤醒</b><b></b>

模拟线程之间的协作。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&lt;" + id + "&gt;";

    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&lt;Athlete&gt; players = new HashSet&lt;Athlete&gt;();

    private boolean start = false;

    public void addPlayer(Athlete one) {

      players.add(one);

    public void removePlayer(Athlete one) {

      players.remove(one);

    public Collection&lt;Athlete&gt; 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&lt;Athlete&gt; iter = getPlayers().iterator();

      while (iter.hasNext())

        new Thread(iter.next()).start();

      start = false;

      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 &lt; 10; i++)

        game.addPlayer(new Athlete(i, game));

      new Thread(game).start();

}

结果:

Ready......

Athlete&lt;0&gt; ready!

Athlete&lt;1&gt; ready!

Athlete&lt;2&gt; ready!

Athlete&lt;3&gt; ready!

Athlete&lt;4&gt; ready!

Athlete&lt;5&gt; ready!

Athlete&lt;6&gt; ready!

Athlete&lt;7&gt; ready!

Athlete&lt;8&gt; ready!

Athlete&lt;9&gt; ready!

Go!

Athlete&lt;9&gt; go!

Athlete&lt;8&gt; go!

Athlete&lt;7&gt; go!

Athlete&lt;6&gt; go!

Athlete&lt;5&gt; go!

Athlete&lt;4&gt; go!

Athlete&lt;3&gt; go!

Athlete&lt;2&gt; go!

Athlete&lt;1&gt; go!

Athlete&lt;0&gt; go!

<b>3.</b><b>模拟忙等待过程</b><b></b>

MyObject类的实例是被观察者,当观察事件发生时,它会通知一个Monitor类的实例(通知的方式是改变一个标志位)。而此Monitor类的实例是通过忙等待来不断的检查标志位是否变化。

BusyWaiting.java

import java.util.concurrent.TimeUnit;

class MyObject implements Runnable {

    private Monitor monitor;

    public MyObject(Monitor monitor) {

      this.monitor = monitor;

      try {

        TimeUnit.SECONDS.sleep(3);

        System.out.println("i'm going.");

        monitor.gotMessage();

        e.printStackTrace();

      }

class Monitor implements Runnable {

    private volatile boolean go = false;

    public void gotMessage() throws InterruptedException {

      go = true;

    public void watching() {

      while (go == false)

        ;

      System.out.println("He has gone.");

      watching();

public class BusyWaiting {

      Monitor monitor = new Monitor();

      MyObject o = new MyObject(monitor);

      new Thread(o).start();

      new Thread(monitor).start();

i'm going.

He has gone.

<b>4.</b><b>使用</b><b>wait()</b><b>与</b><b>notify()</b><b>改写上面的例子</b><b></b>

下面的例子通过wait()来取代忙等待机制,当收到通知消息时,notify当前Monitor类线程。

Wait.java

package concurrency.wait;

        TimeUnit.SECONDS.sleep(3);

        System.out.println("i'm going.");

        monitor.gotMessage();

        e.printStackTrace();

    public synchronized void gotMessage() throws InterruptedException {

      go = true;

      notify();

    public synchronized void watching() throws InterruptedException {

        wait();

        watching();

      } catch (InterruptedException e) {

        e.printStackTrace();

public class Wait {

本文转自zhangjunhd51CTO博客,原文链接:http://blog.51cto.com/zhangjunhd/71387,如需转载请自行联系原作者