多线程间的通信 wait()、notify()、notifyAll()

来源:互联网 发布:斑马gk888t编辑软件 编辑:程序博客网 时间:2024/06/07 07:25

多线程如何进行线程间的通信

测试代码:

// class Servicepublic class Service {    public void testMethod(Object lock) {        try{            synchronized (lock) {                System.out.println("begin wait() ThreadName="                        + Thread.currentThread().getName());                lock.wait();                System.out.println("end wait() ThreadName="                        + Thread.currentThread().getName());            }        } catch(InterruptedException e) {            e.printStackTrace();        }    }}// class ThreadApublic class ThreadA extends Thread{    private Object lock;    public ThreadA(Object lock) {        this.lock = lock;    }    @Override    public void run() {        Service s = new Service();        s.testMethod(lock);    }}// class ThreadBpublic class ThreadB  extends Thread{    private Object lock;    public ThreadB(Object lock) {        this.lock = lock;    }    @Override    public void run() {        Service s = new Service();        s.testMethod(lock);    }}// class ThreadCpublic class ThreadC  extends Thread{    private Object lock;    public ThreadC(Object lock) {        this.lock = lock;    }    @Override    public void run() {        Service s = new Service();        s.testMethod(lock);    }}// class NotifyThreadpublic class NotifyThread extends Thread{    private Object lock;    public NotifyThread(Object lock) {        this.lock = lock;    }    @Override    public void run() {        synchronized (lock) {            lock.notify();//          lock.notify();//          lock.notify();//          lock.notify();//          lock.notifyAll();        }    }}// class Mainpublic class Main {    public static void main(String[] args) {        service();    }    private static void service() {        try{            Object lock = new Object();            ThreadA ta = new ThreadA(lock);            ta.start();            ThreadB tb = new ThreadB(lock);            tb.start();            ThreadC tc = new ThreadC(lock);            tc.start();            Thread.sleep(3000); // 主线程睡眠3秒钟            NotifyThread notifyThread = new NotifyThread(lock);            notifyThread.start();        } catch(InterruptedException e) {            e.printStackTrace();        }    }}

输出结果(程序还在执行状态,并没有退出,因为还有两个线程处于等待状态):

begin wait() ThreadName=Thread-0begin wait() ThreadName=Thread-1begin wait() ThreadName=Thread-2end wait() ThreadName=Thread-0

从以上输出中我们可以得知Thread-0首先获得了lock对象的对象锁,然后执行到lock.wait()后,Thread-0线程进入等待状态并释放了lock对象的对象锁、然后是Thread-1、Thread-2线程依次执行Thread-0的步骤。最后三个线程均进入等待状态并将lock对象的对象锁释放掉。主线程在等待了三秒后创建了notifyThread对象并新创建了一个线程,notifyThread线程获取lock对象的对象锁后执行lock.notify()方法随机唤醒三个等待线程中的一个(从打印结果看出随机唤醒的是Thread-0),被唤醒的线程继续执行lock.wait()后续代码,直至该线程的任务执行完毕。

结论:notify一次只能随机唤醒一个在等待的线程,如果存在多个等待线程,其他没被唤醒的线程会继续等待下去。

将NotifyThread的run方法内的lock.notify()全部解开注释,如下:

@Overridepublic void run() {    synchronized (lock) {        lock.notify();        lock.notify();        lock.notify();        lock.notify();//      lock.notifyAll();    }}

执行后的输出结果:

begin wait() ThreadName=Thread-0begin wait() ThreadName=Thread-1begin wait() ThreadName=Thread-2end wait() ThreadName=Thread-0end wait() ThreadName=Thread-2end wait() ThreadName=Thread-1

从以上输出结果可以看出,虽然执行了四次lock.notify()方法,但是只有三个线程处于等待状态,多次执行lock.notify()会被系统自动忽略。每次执行完lock.notify()方法后都会随机唤醒一个处于等待状态的线程。

我们将NotifyThread的run方法内的lock.notify();方法全部注释掉,解开lock.notifyAll();的注释代码,如下所示:

@Overridepublic void run() {    synchronized (lock) {//      lock.notify();//      lock.notify();//      lock.notify();//      lock.notify();        lock.notifyAll();    }}

再次执行后输出如下:

begin wait() ThreadName=Thread-0begin wait() ThreadName=Thread-2begin wait() ThreadName=Thread-1end wait() ThreadName=Thread-1end wait() ThreadName=Thread-2end wait() ThreadName=Thread-0

从以上结果可以看出,lock.notifyAll()方法会将所有处于等待的线程全部唤醒,也就不需要去关心有多少线程处于等待状态了。

通过wait()和notify(),notifyAll()方法可以实现线程件的通信。

阅读全文
0 0
原创粉丝点击