Java 线程等待、通知、通知全部

线程等待、通知、通知全部

java 中的Object类包含三个final 方法

  • wait()
  • notify()
  • notifyAll()

简介

在任何对象上调用这些方法的当前线程应该具有对象监视器,否则会抛出

java.lang.IllegalMonitorStateException

等待

wait()

对象等待方法由三个

  • 一个是等待无限期,等待其他任何线程调用对象上的notify或notifyAll方法来唤醒当前线程;
  • 另外两个是是当前线程在唤醒前等待特定的时间间隔

通知

notify 方法只唤醒一个等待该对象的线程,该线程开始执行。

如果有多个线程在等待对象,则此方法将仅唤醒其中的一个,要唤醒的线程取决于线程管理的OS

通知全部

notifyAll 唤醒等待对象的所有线程,但首先唤醒哪个线程仍由OS决定

这些方法会产生生产者消费者问题,消费者线程正在等待队列中的对象,生产者线程将对象放入队列并通知等待的线程

举例

package coreofjava.javathread.threadwaitnotifyandnotifyall;

public class Message {
    private String msg;

    public Message(String str) {
        this.msg = str;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String str) {
        this.msg = str;
    }
}

线程将在其上工作的java bean类,并调用 wait 和 notify 方法

package coreofjava.javathread.threadwaitnotifyandnotifyall;

public class Waiter implements Runnable{
    private Message msg;

    public Waiter(Message m) {
        this.msg = m;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        synchronized (msg) {
            try {
                System.out.println(name + " 等待通知, 时间 : " + System.currentTimeMillis());
                msg.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name + " 等待线程获得通知 , 时间 : " + System.currentTimeMillis());

            // 处理消息

            System.out.println(name + " 已处理 : " + msg.getMsg());
        }
    }
}

将等待其他线程调用 notify 类来完成处理的类, Waiter 线程使用 synchronized 块在 Message 对象上拥有监视器

package coreofjava.javathread.threadwaitnotifyandnotifyall;

public class Notifier implements Runnable {
    private Message msg;

    public Notifier(Message msg) {
        this.msg = msg;
    }


    /**
     * 如果只调用 notify() 则线程中的一个被调用,另一个被挂起,则程序不会结束
     * 如果使用 notifyAll(), 则所有线程将会被运行
     */

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " 开始");
        try {
            Thread.sleep(1000);
            synchronized (msg) {
                msg.setMsg(name + " 通知工作完成");
                msg.notify();
//                msg.notifyAll();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

将在 Message 对象上处理然后调用 notify方法来唤醒等待 Message对象的线程的类。 synchronized 块用于拥有 Message对象的监视器

package coreofjava.javathread.threadwaitnotifyandnotifyall;

public class WaitNotifyTest {
    public static void main(String[] args) {
        Message msg = new Message(" 开始处理");
        Waiter waiter = new Waiter(msg);
        new Thread(waiter, "waiter").start();

        Waiter waiter1 = new Waiter(msg);
        new Thread(waiter1, "waiter1").start();

        Notifier notifier = new Notifier(msg);
        new Thread(notifier, "notifier").start();
        System.out.println("所有线程开始");
    }
}

测试类将创建Waiter和 Notifier 的多个线程并启动

当通知类使用 notify() 只有一个线程被调用, 若使用 notifyAll ,则所有线程将被调用

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容