`

notify()和notifyAll() 本质区别 --- 示例 (转)

 
阅读更多

notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。两者的最大区别在于:

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

下面是一个很好的例子:

import java.util.*;

class Widget...{}
class WidgetMaker extends Thread...{
    List<Widget> finishedWidgets=new ArrayList<Widget>();
    public void run()...{
        try...{
            while(true)...{
                Thread.sleep(5000);//act busy
                Widget w=new Widget();
                //也就是说需要5秒钟才能新产生一个Widget,这决定了一定要用notify而不是notifyAll
                //因为上面两行代码不是同步的,如果用notifyAll则所有线程都企图冲出wait状态
                //第一个线程得到了锁,并取走了Widget(这个过程的时间小于5秒,新的Widget还没有生成)
                //并且解开了锁,然后第二个线程获得锁(因为用了notifyAll其他线程不再等待notify语句
                //,而是等待finishedWidgets上的锁,一旦锁放开了,他们就会竞争运行),运行
                //finishedWidgets.remove(0),但是由于finishedWidgets现在还是空的,
                //于是产生异常
                //***********这就是为什么下面的那一句不能用notifyAll而是要用notify
                               
                synchronized(finishedWidgets)...{
                    finishedWidgets.add(w);
                    finishedWidgets.notify(); //这里只能是notify而不能是notifyAll
                }
            }
        }
        catch(InterruptedException e)...{}
    }
   
    public Widget waitForWidget()...{
        synchronized(finishedWidgets)...{
            if(finishedWidgets.size()==0)...{
                try...{
                    finishedWidgets.wait();
                }
                catch(InterruptedException e)
                ...{}
            }
            return 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.waitForWidget();
        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();

    }

}

分享到:
评论

相关推荐

    java基础知识大全

    - 功能:使当前线程放弃对象锁并进入等待状态,直到收到`notify()`或`notifyAll()`通知后才有机会重新获取锁。 #### Overload与Override的区别 - **Overloading**(重载): - 概念:在同一类中,允许存在一个...

    Thinking_In_Java

    这本书以其详尽的解释、丰富的示例和对Java本质的理解而备受赞誉。以下将根据书名和描述,结合“java”这一标签,探讨Java编程语言的核心知识点。 1. **Java基础** - **变量与数据类型**:Java有基本数据类型(如...

    WEB多线程开发

    - **线程通信**:了解`wait()`, `notify()`, `notifyAll()`方法以及`BlockingQueue`等同步机制,用于线程间的通信和协作。 - **异常处理**:确保线程在执行过程中正确处理异常,防止整个应用因为单个线程的问题而...

    Thinking.In.Java.3rd.Edition.Chinese.eBook

    6. **多线程**:Java提供了内置的多线程支持,包括Thread类和Runnable接口,以及同步机制如synchronized关键字、wait()、notify()和notifyAll()方法。 7. **输入/输出流**:Java的I/O流系统涵盖了文件读写、网络...

    Thinking in Java, 3rd ed.

    6. **多线程**:讲述了如何在Java中创建和管理线程,以及同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法。 7. **输入/输出(I/O)**:包括文件操作、流的概念、序列化和网络I/O,这对于处理...

    java并发编程笔记

    - `wait`: 属于`Object`类的方法,用于使当前线程等待,直到其他线程调用此对象上的`notify()`或`notifyAll()`方法。 - `sleep`: 属于`Thread`类的静态方法,用于使当前正在执行的线程暂停执行指定的时间。 - **锁...

    thinking in java

    5. **多线程编程**:Java支持多线程编程,书中介绍了线程的创建、同步和通信,包括synchronized关键字、wait()、notify()和notifyAll()方法,以及线程池的使用,让开发者能够编写高效的并发程序。 6. **输入/输出和...

    Think injava

    线程同步机制(如synchronized关键字、wait()、notify()和notifyAll()方法、Lock接口等)用于解决并发编程中的线程安全问题。 7. **泛型**:泛型引入于Java 5,用于在编译时检查类型安全,并且允许在代码中存储任意...

    java_concurrency_in_practice_source源代码

    源码中会包含各种同步机制的示例,如同步方法、同步代码块、`wait()`、`notify()`和`notifyAll()`等。 3. **死锁与活锁**:死锁是指两个或多个线程互相等待对方释放资源导致无法继续执行的情况。活锁则是线程虽然...

    多线程并发的demo

    `wait()`, `notify()`, `notifyAll()`方法用于线程间的通信和协作;`java.util.concurrent`包下有各种高级并发工具,如`Semaphore`(信号量)用于控制同时访问特定资源的线程数量,`CyclicBarrier`和`CountDownLatch`...

    java高并发源码-act_java_concurrent_src:《实战Java高并发程序设计》

    7. **线程通信**:Java的`wait()`, `notify()`, `notifyAll()`方法和`java.util.concurrent`包中的`Condition`接口,提供了线程间通信的方式,使得线程能够协调执行。 8. **并发工具类**:包括CountDownLatch、...

    Java锁之阻塞锁介绍和代码实例

    阻塞锁,作为Java并发控制的一种重要手段,与自旋锁有着本质的区别。自旋锁会让线程在未获取锁时持续循环检查,直到获取到锁为止,而阻塞锁则会直接使线程进入阻塞状态,等待被其他线程唤醒。 在Java中,线程有五种...

Global site tag (gtag.js) - Google Analytics