Java 线程:notify() 和 wait() 示例

原文地址:http://www.programcreek.com/2009/02/notify-and-wait-example/

本文包含了两个 Java 并发 的代码示例,它们代表了非常典型的用法。 通过了解它们,你将更好地了解 notify()wait() 方法。

1. 背景知识

  1. synchronized 关键字用于独占访问。
  2. 要使方法同步,只需将 synchronized 关键字添加到其声明中即可。 所以同一个对象上没有两个同步方法的调用是可以互相交错(interleave)的。
  3. 同步语句必须指定提供内在锁的对象。 当使用 synchronized(this) 时,必须避免同步调用其他对象的方法。
  4. wait() 通知调用线程放弃监视器并进入休眠状态,直到某个其他线程进入同一个监视器并调用 notify()
  5. notify() 将唤醒同一对象上第一个调用 wait() 方法的线程。

2. 示例 1

public class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();

        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }

            System.out.println("Total is: " + b.total);
        }
    }
}

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}

在上面的例子中,对象 b 是同步的,b 在主线程输出其总值之前完成计算。

所以上面的输出结果为:

Waiting for b to complete...
Total is: 4950

如果 b 不是同步的,就像下面的代码这样:

public class ThreadA {
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();

        System.out.println("Total is: " + b.total);

    }
}

class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
    }
}

那么结果可能是 0,10,因为在使用 total 时它可能还没有完成计算。

3. 示例 2

第二个例子可能有点复杂:

import java.util.Vector;

class Producer extends Thread {

    static final int MAXQUEUE = 5;
    private Vector messages = new Vector();

    @Override
    public void run() {
        try {
            while (true) {
                putMessage();
                //sleep(5000);
            }
        } catch (InterruptedException e) {
        }
    }

    private synchronized void putMessage() throws InterruptedException {
        while (messages.size() == MAXQUEUE) {
            wait();
        }
        messages.addElement(new java.util.Date().toString());
        System.out.println("put message");
        notify();
        //Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object.
    }

    // Called by Consumer
    public synchronized String getMessage() throws InterruptedException {
        notify();
        while (messages.size() == 0) {
            wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
        }
        String message = (String) messages.firstElement();
        messages.removeElement(message);
        return message;
    }
}

class Consumer extends Thread {

    Producer producer;

    Consumer(Producer p) {
        producer = p;
    }

    @Override
    public void run() {
        try {
            while (true) {
                String message = producer.getMessage();
                System.out.println("Got message: " + message);
                //sleep(200);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        Producer producer = new Producer();
        producer.start();
        new Consumer(producer).start();
    }
}

可能的输出顺序:

Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011

results matching ""

    No results matching ""