博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java交互:通知和等待
阅读量:4290 次
发布时间:2019-05-27

本文共 3696 字,大约阅读时间需要 12 分钟。

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

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

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

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

注意:

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

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

二、举个例子:

/** * 计算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();         }     } }

 

/** * 计算输出其他线程锁计算的数据* 在类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);        }     } }

计算结果:等待对象b完成计算。。。b对象计算的总和是:5050 

 

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

 

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

a)        举个例子:

i. 

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

ii.            

/** * 获取计算结果并输出 */ 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();         } }

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

 

你可能感兴趣的文章
仿主流APP功能实现
查看>>
Java读取文件夹大小的6种方法及代码
查看>>
Java多线程中的10个面试要点
查看>>
Java面试经典,小题目大学问
查看>>
《程序员》:携程移动端 UI 界面性能优化实践
查看>>
Android指纹识别深入浅出分析到实战
查看>>
你们要的多数据库功能终于来了
查看>>
Android中实现微信本地视频发布到朋友圈功能
查看>>
非替代品,MongoDB与MySQL对比分析
查看>>
Hadoop平台相关技术
查看>>
java学习11天-自定义异常&异常转换(实例应用)
查看>>
MySql、SqlServer、Oracle数据库行转列大全
查看>>
程序员常用的自助建站资源汇总!
查看>>
分布式与集群的区别是什么?
查看>>
MySql常用必备脚本大全
查看>>
Velocity初探小结--velocity使用语法详解
查看>>
设计模式学习 - Singleton Pattern
查看>>
学习Spring——依赖注入
查看>>
CSS3 transform 属性详解
查看>>
Java对象内存结构及大小计算
查看>>