为什么80%的码农都做不了架构师?>>>   

JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。明白这个原理,就能理解为什么synchronized(this)与synchronized(static XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类的一个对象,所以其内存锁是针对相同对象的互斥操作,而static成员属于类专有,其内存空间为该类所有成员共有,这就导致synchronized()对static成员加锁,相当于对类加锁,也就是在该类的所有成员间实现互斥,在同一时间只有一个线程可访问该类的实例。如果只是简单的想要实现在JAVA中的线程互斥,明白这些基本就已经够了。但如果需要在线程间相互唤醒的话就需要借助Object.wait(), Object.nofity()了。

wait与notify是java同步机制中重要的组成部分。结合与synchronized关键字使用,可以建立很多优秀的同步模型。
     synchronized(this){}等价与public synchronized void method(){.....}
     同步分为类级别和对象级别,分别对应着类锁和对象锁。类锁是每个类只有一个,如果static的方法被synchronized关键字修饰,则在这个方法被执行前必须获得类锁;对象锁类同。(static synchronized是类级别的,非static的synchronized和synchronized块都是对象级别的,即作用在同一new出来的对象上)
     首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){......}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:
     java.lang.IllegalMonitorStateException: current thread not owner
     在调用wait的时候,线程自动释放其占有的对象锁,同时不会去申请对象锁。当线程被唤醒的时候,它才再次获得了去获得对象锁的权利。
     所以,notify与notifyAll没有太多的区别,只是notify仅唤醒一个线程并允许它去获得锁,notifyAll是唤醒所有等待这个对象的线程并允许它们去获得对象锁,只要是在synchronied块中的代码,没有对象锁是寸步难行的。其实唤醒一个线程就是重新允许这个线程去获得对象锁并向下运行。       顺便说一下notifyall,虽然是对每个wait的对象都调用一次notify,但是这个还是有顺序的,每个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。其实启动等待对象链中各个线程的也是一个线程,在具体应用的时候,需要注意一下。

应用实例:

建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就可以很方便的解决。

package cn.com.thread;/*** Description: <交替打印10次ABC>. <br>* <p>* <使用说明>* </p>* Makedate:2014-4-12 下午2:14:19* * @author gaowenming* @version V1.0*/
public class WaitAndNotifyTest {/*** 描述 : <描述函数实现的功能>. <br>* <p>* <使用方法说明>* </p>* * @param args*/public static void main(String[] args) {final PrintABC printAbc = new PrintABC();// 循环加载外层for (int i = 0; i < 10; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {printAbc.printA(); // printA} catch (Exception e) {e.printStackTrace();}}}).start();new Thread(new Runnable() {@Overridepublic void run() {try {printAbc.printB();// printB} catch (Exception e) {e.printStackTrace();}}}).start();new Thread(new Runnable() {@Overridepublic void run() {try {printAbc.printC();// printC} catch (Exception e) {e.printStackTrace();}}}).start();}}}/*** * * @Description: 交替打印10次ABC* @author gaowenming* @date 2014-4-12 下午2:17:11* */
class PrintABC {// 定义全局变量boolean a = true;boolean b = false;boolean c = false;public synchronized void printA() throws Exception {// 用while,表示一直等待while (!a) {this.wait();}System.out.print("A");a = false;b = true;// 执行完后唤醒其他等待的线程notifyAll();}public synchronized void printB() throws Exception {while (!b) {this.wait();}System.out.print("B");b = false;c = true;notifyAll();}public synchronized void printC() throws Exception {while (!c) {this.wait();}System.out.println("C");c = false;a = true;notifyAll();}
}

运行结果:

ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC

转载于:https://my.oschina.net/gaowm/blog/221385

java并发编程(2)——wait和notify解析相关推荐

  1. 【Java并发编程:volatile关键字之解析】

    Java并发编程:volatile关键字解析 - Matrix海子 - 博客园 在Java 5之前,volatile是一个备受争议的关键字:因为在程序中使用它往往会导致出人意料的结果.在Java 5之 ...

  2. java并发编程学习三——wait/notify与park/unpark

    文章目录 一.wait/notify 1.1 api的使用 1.2 wait(long n)与sleep(long n) 1.3 正确使用方式 1.3.1 基本方式 1.3.2 保护性暂停模式 1.3 ...

  3. Java并发编程之线程定时器ScheduledThreadPoolExecutor解析

    定时器 就是需要周期性的执行任务,也叫调度任务,在JDK中有个类Timer是支持周期性执行,但是这个类不建议使用了. ScheduledThreadPoolExecutor 继承自ThreadPool ...

  4. Java并发编程之线程池ThreadPoolExecutor解析

    线程池存在的意义 平常使用线程即new Thread()然后调用start()方法去启动这个线程,但是在频繁的业务情况下如果在生产环境大量的创建Thread对象是则会浪费资源,不仅增加GC回收压力,并 ...

  5. Java 并发编程解析 | 如何正确理解Java领域中的锁机制,我们一般需要掌握哪些理论知识?

    苍穹之边,浩瀚之挚,眰恦之美: 悟心悟性,善始善终,惟善惟道! -- 朝槿<朝槿兮年说> 写在开头 提起Java领域中的锁,是否有种"道不尽红尘奢恋,诉不完人间恩怨"的 ...

  6. 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  7. Java并发编程 Volatile关键字解析

    volatile关键字的两层语义 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了 ...

  8. Java并发编程—notify和notifyAll有什么区别?

    原文作者:知乎用户 原文地址:https://www.zhihu.com/question/37601861/answer/145545371 著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  9. Java并发编程—线程间协作方式wait()、notify()、notifyAll()和Condition

    原文作者:Matrix海 子 原文地址:Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 目录 一.wait().notify()和notifyA ...

最新文章

  1. Zookeeper集群搭建分布式
  2. 网易实战分享|Docker文件系统实战
  3. 【arc068F】Solitaire
  4. RePlugin 插件化方案学习
  5. STM32工作笔记0051---NVIC中断优先级管理
  6. L1-035 情人节 (15 分)—团体程序设计天梯赛
  7. 智能判断图片中是否存在某物体_RFID新技术:让所有物体联网!
  8. 厉害了,大米云Linux搭建Wordpress环境
  9. ARM V8 SPEC B1 AArch64 Application level programer‘s Model
  10. PMP ITTO 和 4W1H
  11. mac adb安装和使用
  12. java中intern_Java中的intern()方法是什么?
  13. 为什么银行的现钞买入价低于现汇买入价?
  14. iOS APP之间到跳转,以及热门应用,手机自带到应用跳转
  15. 千住焊锡丝RMA98,ESC21参数解读:金属含量、焊剂成分、质保期、Lot No. 等
  16. poi 颜色对照表
  17. 李兴华内部JAVA培训视频 (难找啊)
  18. oracle 表信息查询,oracle 表信息查询
  19. 中兴新支点助力抗洪抢险应急演练,多角度、全方位细节一览无余!
  20. GNU Make 使用手册(于凤昌中译版)

热门文章

  1. 2017年前端工作小结,个人踩坑之旅,前端学习者的杂谈
  2. 不仅仅是商务旗舰,金立M2017的拍照实力同样给力
  3. C# 获取MAC地址
  4. 【hadoop2.6.0】利用Hadoop的 Java API
  5. DropDownList的值去控制TextBox是否可编写
  6. 计算机二级为什么无法登录,解决因登录失败而无法启动SQL服务
  7. php 获取企业号用户,微信企业号 获取用户信息(示例代码)
  8. Auto.js 抖音--留痕--参数分析
  9. 【MaxCompute】学习笔记操作表sql
  10. Codeforces Round 542 (Div. 2)