java交互:通知和等待

一、线程交互的基础知识(通知和等待)

a)        void notify() 唤醒在此对象监视器上等待的单个线程

b)        void notifyAll() 唤醒在此对象监视器上等待的所有线程

c)        void wait() 使当前线程等待,知道其他线程调用此对象的notify()和notifyAll()方法

注意:

1、  必须从同步环境内调用wait()、notify()、norifyAll()方法。线程不能随意调用对象上等待或通知(notify)的方法,除非它拥有那个对象的锁 

2、  wait(),notify(),notifyAll()都是Object类的实例方法。与每个对象具有锁一样,每个对象可以有一个线程列表,他们等待通知信号。线程通过执行对象上的wait()方法获得等待列表。

二、举个例子:

<span style="font-size:18px;">/** 
* 计算1+2+3 ... +100的和
*  创建线程ThreadB
*/ 
public class ThreadB extends Thread {
    int total; 

    publicvoid run() {
        synchronized (this) {//为线程ThreadB的run()方法加锁
            for (int i = 0; i < 101; i++) {
                total+= i; 
            } 
         //(完成计算了)唤醒在此对象监视器上等待的单个线程,在本例中类ThreadA的main主线程被唤醒
            notify(); 
        } 
    } 
}</span>


 

<span style="font-size:18px;">/** 
* 计算输出其他线程锁计算的数据
* 在类ThreadA中,创建线程ThreadB,并使线程ThreadB处于可运行状态
*/ 
public class ThreadA {
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        //启动计算线程
        b.start(); 
        //类ThreadA的main主线程拥有线程ThreadB 类的实例b对象上的锁。类ThreadA的main主线程为了调用wait()或notify()方法,该类ThreadA的main主线程必须是那个对象b锁的拥有者
        synchronized (b) {
            try {
                System.out.println("等待对象b完成计算。。。");
                //当前线程A等待
                b.wait(); 
            } catch (InterruptedException e) {
                e.printStackTrace(); 
            } 
            System.out.println("b对象计算的总和是:" + b.total);
        } 
    } 
}</span>


<span style="font-size:18px;">计算结果:
等待对象b完成计算。。。
b对象计算的总和是:5050 </span>


 

注意:当在对象上调用wait()方法时,执行该代码的线程立即放弃他在对象上的锁(上例中,在ThreadA类的main主线程中,调用对象b的wait()方法,则执行该代码的main主线程立即放弃main主线程在对象b上的锁,即类ThreadA中的synchronized (b)锁)。然而调用notify时,并不意味着这时线程会放弃其锁(线程ThreadB的synchronized (this)),如果线程依然在完成同步代码(即notify后面还有要执行的代码),则线程在移除以前不会放弃锁(线程ThreadB的synchronized (this))。

 

三、多个线程在等待一个对象锁

a)        举个例子:

i. 

<span style="font-size:18px;">/** 
* 计算线程 
*/ 
public class Calculator extends Thread {
        int total;
        public void run() {
                synchronized (this) {
                        for (int i = 0; i < 101; i++) {
                                total+= i; 
                        } 
                } 
                //通知所有在此对象上等待的线程
                notifyAll(); 
        } 
}</span>


ii.            

 <span style="font-size:18px;">/** 
* 获取计算结果并输出 
*/ 
public class ReaderResult extends Thread {
        Calculator c; 

        public ReaderResult(Calculator c) {
                this.c = c;
        } 

        public void run() {
                synchronized (c) {
                        try {
                                System.out.println(Thread.currentThread()+ "等待计算结果。。。");
                                c.wait(); 
                        } catch (InterruptedException e) {
                                e.printStackTrace(); 
                        } 
                        System.out.println(Thread.currentThread()+ "计算结果为:" + c.total);
                } 
        } 

        public static void main(String[] args) {
                Calculatorcalculator = new Calculator();

                //启动三个线程,分别获取计算结果
                new ReaderResult(calculator).start();
                new ReaderResult(calculator).start();
                new ReaderResult(calculator).start();
                //启动计算线程
                calculator.start(); 
        } 
}</span>


iii.  运行结果:

Thread[Thread-1,5,main]等待计算结果。。。
Thread[Thread-2,5,main]等待计算结果。。。
Thread[Thread-3,5,main]等待计算结果。。。
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException:current thread not owner
  at java.lang.Object.notifyAll(Native Method) 
  at threadtest.Calculator.run(Calculator.java:18) 
Thread[Thread-1,5,main]计算结果为:5050
Thread[Thread-2,5,main]计算结果为:5050
Thread[Thread-3,5,main]计算结果为:5050

b)        这样写程序中有异常,下面分析一下

                        i.             上面的代码,我们期望的是,读取结果的线程ReaderResult在计算线程Calculator调用notifyAll()之前,等待即可。

                      ii.             如果计算线程已经调用了notifyAll()方法,那么它就不会再次调用notifyAll(),

                     iii.             解决上面异常的方法是Calculator类中的  notifyAll(); 放到  synchronized (this) {}里面,如图:

                    


参考文章:http://www.cnblogs.com/riskyer/p/3263032.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值