Java notify()和notifyAll()同步唤醒上的区别

notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法

  • void notify(): 唤醒一个正在等待该对象的线程。
  • void notifyAll(): 唤醒所有正在等待该对象的线程。

两者的最大区别在于:

  • notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
  • notify他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁,此时如果该对象没有再次使用notify语句,即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。

多个线程拥有同一个同步对象时,用notifyAll会造成异常的实例

import java.util.ArrayList;
import java.util.List;

class Widget{}
class WidgetMaker extends Thread{
    List finishedWidgets = new ArrayList();
    public void run(){
         try{
             while(true){
                // 每5s产生对象加入List
                 Thread.sleep(5000);
                 Widget w = new Widget();
                 Widget i = new Widget();
                 Widget d = new Widget();
                 synchronized (finishedWidgets) {
                    finishedWidgets.add(w);
                    finishedWidgets.add(i);
                    finishedWidgets.add(d);
                    // 向List加入3个元素后通知wait对象唤醒
                    // 如果此处使用notifyAll(),第一个线程得到了锁,而其他线程也从wait状态被唤醒执行remove命令,部分List会出现空元素remove出现异常,notify则只选择当前wait状态线程进行唤醒,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们
                    finishedWidgets.notify();
                }
             }
         }catch(InterruptedException e) {}
         }
    // 如果List中有就一直返回,直到List为空时wait
    public Widget waitForWiget() {
        synchronized (finishedWidgets) {
            if (finishedWidgets.size() == 0) {
                try {
                    finishedWidgets.wait();
                } catch (InterruptedException e) {
                }
            }
            return (Widget) finishedWidgets.remove(0);
        }
    }
}

public class WidgetUser extends Thread{
    private WidgetMaker maker;
    public WidgetUser(String name,WidgetMaker maker){
        super(name);
        this.maker = maker;
    }

    public void run(){
        Widget w = maker.waitForWiget();
        System.out.println(getName()+"got a widget");
    }

    public static void main(String[] args){
        WidgetMaker maker = new WidgetMaker();
        maker.start();
        new WidgetUser("Lenny", maker).start();
        new WidgetUser("Moe", maker).start();
        new WidgetUser("Curly", maker).start();
    }

}
时间: 2024-10-09 16:44:31

Java notify()和notifyAll()同步唤醒上的区别的相关文章

线程同步以及yield()、wait()、Notify()、Notifyall()

一.线程同步 1.线程同步的目的是为了保护多个线程访问一个资源时对资源的破坏. 2.线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他同步方法. 二.实现同步机制的两个方法 1.同步代码块: synchronized(同一个数据){} 同一个数据:就是N条线程同时访问一个数据. 2. 同步方法: public synchronized 数据返回类型 方法名(){} 就是使用 synchronized

通过两个小栗子来说说Java的sleep、wait、notify、notifyAll的用法

线程是计算程序运行的最小载体,由于单个单核CPU的硬件水平发展到了一定的瓶颈期,因此就出现了多核多CPU的情况,直接就导致程序员多线程编程的复杂.由此可见线程对于高性能开发的重要性. 那么线程在计算机中有好几种状态,他们之间是怎么切换的?sleep和wait又有什么区别?notify和notifyAll怎么用?带着这些问题,我们来看看Java的线程吧! Thread的状态 先来看看Thread类里面都有哪几种状态,在Thread.class中可以找到这个枚举,它定义了线程的相关状态: publi

Java多线程中wait, notify and notifyAll的使用

本文为翻译文章,原文地址:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example 在Java的Object类中有三个final的方法允许线程之间进行资源对象锁的通信,他们分别是: wait(), notify() and notifyAll(). 调用这些方法的当前线程必须拥有此对象监视器,否则将会报java.lang.IllegalMonitorStateException exception异常

notify和notifyAll有什么区别

1 /* 2 * 文件名:NotifyDeadLockDemo.java 3 * 版权:Enmuser Technologies Co.,Ltd. Copyright 2016-2018 4 * 描述:<描述> 5 * 修改人:enmuser 6 * 修改时间:2018年2月24日 7 * 修改单号:<修改单号> 8 * 修改内容:<修改内容> 9 * 10 */ 11 package notify.deadLock; 12 13 /** 14 * <一句话功能描

Java的wait(), notify()和notifyAll()使用心得(转)

本篇文章是对java的 wait(),notify(),notifyAll()进行了详细的分析介绍,需要的朋友参考下wait(),notify()和notifyAll()都是java.lang.Object的方法:wait(): Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.notify():

如何使用wait(), notify() and notifyAll() – Java

Java多线程是个很复杂的问题,尤其在多线程在任何给定的时间访问共享资源需要更加注意.Java 5引入了一些类比如BlockingQueue 和Executors 类提供了易于使用的API,避免了一些复杂性.使用这些类比直接使用wait()和notify()同步处理的让程序员感到更加自信.我也推荐使用这些新的API来同步,但是很多时候我们出于各种原因需要旧方式,例如维护遗留代码.在这些情况下,熟悉这些方法将有助于你理解.在本教程中,我讨论关于wait(),notify()和notifyall()

Java线程中sleep()、wait()和notify()和notifyAll()、yield()、join()等方法的用法和区别

Java线程中sleep().wait()和notify()和notifyAll().suspend和resume().yield().join().interrupt()的用法和区别 从操作系统的角度讲,os会维护一个ready queue(就绪的线程队列).并且在某一时刻cpu只为ready queue中位于队列头部的线程服务. 但是当前正在被服务的线程可能觉得cpu的服务质量不够好,于是提前退出,这就是yield. 或者当前正在被服务的线程需要睡一会,醒来后继续被服务,这就是sleep. 

Java并发之线程间协作Object的wait()、notify()、notifyAll()

wait().notify()和notifyAll()是Object类中的方法: 1)wait().notify()和notifyAll()方法是本地方法,而且为final方法,无法被重写. 2)调用某个对象的wait()方法能让当前线程堵塞.而且当前线程必须拥有此对象的monitor(即锁) 3)调用某个对象的notify()方法可以唤醒一个正在等待这个对象的monitor的线程,假设有多个线程都在等待这个对象的     monitor.则仅仅能唤醒当中一个线程: 4)调用notifyAll(

(转)为什么wait(),notify()和notifyAll()必须在同步块或同步方法中调用

我们常用wait(),notify()和notifyAll()方法来进行线程间通信.线程检查一个条件后就行进入等待状态,例如,在"生产者-消费者"模型中,生产者线程发现缓冲区满了就等待,消费者线程通过消费一个产品使得缓冲区有空闲并通知生产者线程.notify()或notifyAll()的调用给一个或多个线程发出通知,告诉它(它们)条件已经发生改变,并且,一旦通知线程离开同步块,所有等待这个对象锁的线程将竞争这个对象锁,幸运的线程获得锁后就从wait()方法返回并继续执行.让我们把这整个