JAVA多线程——notify()和notifyAll()的注意事项

来源:互联网 发布:c excel重复数据删除 编辑:程序博客网 时间:2024/06/03 18:59

1. - waiting on <lock id> —— 对应java.lang.Thread.State: WAITING

表示线程执行到了锁的wait()方法上

由于wait()方法会释放锁,所以当前线程此时处于未获取锁状态,等待notify() || notifyAll()

2. - waiting to lock <lock id> —— 对应java.lang.Thread.State: BLOCKED

表示锁已经被其他线程占有,该线程只能进入阻塞状态等待该锁的持有者释放锁再竞争


notify (): 

从等待指定对象(调用notify的对象)的锁的线程中随机选取一个线程执行,其他线程状态仍然为waiting on

如果被选中的线程没有再执行notify或者notifyAll,这些线程可能永远处在waiting on状态

notifyAll() : 

通知所有在等待指定对象的锁的线程退出waiting on状态

进入waiting to lock状态去参与锁的竞争


实例1:生产者与消费者模式

创建共享变量

public class VarHolder {    private boolean needWait = true;    public synchronized void doConsumer() {        while (needWait) {            try {                System.out.println(Thread.currentThread().getName() + "  is going to wait()");                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        needWait = true;        System.out.println(Thread.currentThread().getName() + "   get Notified");    }    public synchronized void doProduce() {        while (!needWait) {            try {                wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        needWait = false;        notify();//        notifyAll();    }}

创建生产者和消费者

public class Producer implements Runnable {    private VarHolder holder;    public Producer(VarHolder holder) {        this.holder = holder;    }    @Override    public void run() {        holder.doProduce();    }}

public class Consumer implements Runnable {    private VarHolder holder;    public Consumer(VarHolder holder) {        this.holder = holder;    }    @Override    public void run() {        holder.doConsumer();    }}

创建测试类
public class TestNotify {    public static void main(String[] args) {        VarHolder holder = new VarHolder();        //启动两个消费者,一个生产者        for (int i = 0; i < 2; i++) {            new Thread(new Consumer(holder), "consumer-" + i).start();        }        //等待1s让consumer线程都进入wait()方法        try {            TimeUnit.SECONDS.sleep(1);        } catch (InterruptedException e) {            e.printStackTrace();        }        new Thread(new Producer(holder), "producer1").start();    }}

分别注释notify()和notifyAll()查看运行结果:
doProduce()执行notify()的结果: 仅仅唤醒一个线程
consumer-0  is going to wait()consumer-1  is going to wait()consumer-0   get Notified

doProduce()执行notifyAll()的结果:
consumer-1  is going to wait()consumer-0  is going to wait()consumer-0   get Notifiedconsumer-1  is going to wait()

可以看到notifyAll()将会唤醒所有线程,导致consumer-1再次调用wait()方法


















0 0
原创粉丝点击