`

java并发 wait,notify,notifyAll,synchronized(一)

 
阅读更多

       首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){......}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:

  java.lang.IllegalMonitorStateException:current thread not owner

 

方法的详细解释:

  wait():

  等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则编译可以通过,但运行时会收到一个异常:IllegalMonitorStateException。

调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。

  notify():

  唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

  notifyAll():

  唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。

 

    可以认为,每个对象实例都有一个wait set线程的休息室,当在该实例调用wait()方法的时候,就将当前线程放入该对象实例的wait set,并释放该对象上的锁。当在改对象上调用notify,或者notifyAll的时候,就是释放该对象wait set休息室里面的线程。

    由此,可以构建一系列的线程安全工具类

 

代码实例:

 

/**
 * 
 */
package com.mutex;

/**
 * 用wait(),notify()实现线程的互斥
 * 
 * 当MainTask运行10次以后,SubTask运行5次,如此依次循环交替执行
 * 
 */
public class MainClient {
	
	//决定线程是否运行
	public static volatile boolean notifyRun=true;
	
	//对象锁
	public static final Object Lock=new Object();
	

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
	
		//主任务运行
		new Thread(new MainTask()).start();
		
		Thread.sleep(1000);
		
		//子任务运行
		new Thread(new SubTask()).start();
		

	}

}

 

 

     

package com.mutex;

public class MainTask implements Runnable {

	private int n = 10;


	@Override
	public void run() {

		while (true) {
			
			System.out.println(" -------- MainTask -----------");
			
			//获取对象MainClient.Lock上的锁
			synchronized (MainClient.Lock) {
				
				if(!MainClient.notifyRun){
					//唤醒MainClient.Lock wait set中的所有线程
					MainClient.Lock.notifyAll();
					MainClient.notifyRun=true;
				}
				
				if(MainClient.notifyRun){
					
					for (int i = 1; i <= n; i++) {
						System.out.println("MainTask run." + i);
					}
					
					try {
						//本线程放入wait set,释放对象MainClient.Lock上的锁
						MainClient.Lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			}

		}

	}
}

 

 

 

    

package com.mutex;

public class SubTask implements Runnable{
	
	private int n=5;
	

	@Override
	public void run() {
		
		while(true){
			
			System.out.println(" -------- SubTask -----------");
			
			//获取对象MainClient.Lock上的锁
			synchronized (MainClient.Lock) {
				
				if(!MainClient.notifyRun){
					try {
						MainClient.Lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					MainClient.notifyRun=true;
				}
				
				for(int i=1;i<=n;i++){
					System.out.println("SubTask run."+i);
				}
				
				
			    //本线程放入wait set,释放对象MainClient.Lock上的锁,让MainTask运行
			    MainClient.Lock.notifyAll();
			    MainClient.notifyRun=false;
			}
			
			
		}
		
		
	}

}

 

 

运行结果:

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

 -------- SubTask -----------

 -------- MainTask -----------

MainTask run.1

MainTask run.2

MainTask run.3

MainTask run.4

MainTask run.5

MainTask run.6

MainTask run.7

MainTask run.8

MainTask run.9

MainTask run.10

SubTask run.1

SubTask run.2

SubTask run.3

SubTask run.4

SubTask run.5

   

 

分享到:
评论

相关推荐

    Java并发编程:设计原则与模式(第二版)

    读者将通过使用java.lang.thread类、synchronized和volatile关键字,以及wait、notify和notifyall方法,学习如何初始化、控制和协调并发操作。此外,本书还提供了有关并发编程的全方位的详细内容,例如限制和同步、...

    java并发编程

    , 这里,读者将通过使用java.lang.thread类、synchronized和volatile关键字,以及wait、notify和notifyall方法,学习如何初始化、控制和协调并发操作。此外,本书还提供了有关并发编程的全方位的详细内容,例如限制...

    【并发编程】 — 线程间的通信wait、notify、notifyAll

    文章目录1 wait、notify、notifyAll简单介绍1.1 使用方法 + 为什么不是Thread类的方法1.2 什么时候加锁、什么时候释放锁?1.3 notify、notifyAll的区别2 两个比较经典的使用案例2.1 案例1 — ABCABC。。。三个线程...

    java高并发相关知识点.docx

    Java高并发相关知识点包括: 线程:Java多线程的实现方式,包括继承Thread类和实现Runnable接口。 锁:Java中的锁机制,包括...线程间通信:Java中的线程间通信,包括wait()、notify()、notifyAll()等方法。

    java并发编程:线程基础

    本资源致力于向您介绍 Java 并发编程中的线程基础,涵盖了多线程编程的核心概念、线程...线程间通信: 详解线程间通信的方法,包括 wait、notify 和 notifyAll 方法的使用。讲解如何通过这些方法实现线程的协作和同步。

    java中的并发和多线程编程中文版

    读者将通过使用java.lang.thread类、synchronized和volatile关键字,以及wait、notify和notifyall方法,学习如何初始化、控制和协调并发操作。此外,本书还提供了有关并发编程的全方位的详细内容,例如限制和同步、...

    Java并发编程:核心理论

    本系列会从线程间协调的方式(wait、notify、notifyAll)、Synchronized及Volatile的本质入手,详细解释JDK为我们提供的每种并发工具和底层实现机制。在此基础上,我们会进一步分析java.util.concurrent包的工具类,...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第一阶段24讲、线程间通信快速入门,使用wait和notify进行线程间的数据通信.mp4 │ 高并发编程第一阶段25讲、多Produce多Consume之间的通讯导致出现程序假死的原因分析.mp4 │ 高并发编程第一阶段26...

    java并发学习笔记

    文章目录1 线程基础、线程之间的共享与协作1.1 cpu时间片轮询机制1.2 进程与线程1.3 并行与并发1.4 启动线程的三种方式1.5 停止线程1.6 线程的生命周期1.7 守护线程1.8 synchronized关键字1.9 volatile关键字1.10 ...

    java多线程设计模式详解(PDF及源码)

    wait set——线程的休息室 wait方法——把线程放入wait set notify方法——从wait set拿出线程 notifyAll方法——从wait set拿出所有线程 wait、notify、notifyAll是Object类的方法 线程的状态移转 跟线程有关的其他...

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第一阶段24讲、线程间通信快速入门,使用wait和notify进行线程间的数据通信.mp4 │ 高并发编程第一阶段25讲、多Produce多Consume之间的通讯导致出现程序假死的原因分析.mp4 │ 高并发编程第一阶段26...

    高级开发并发面试题和答案.pdf

    描述一下notify和notifyAll区别; synchronized关键字加在静态方法和实例方法的区别; 用锁的注意点; cas机制可能导致的问题ABA,什么是ABA; 程序开多少线程合适; 实现一下DCL(双重检查锁) stream 和 parallel...

    这就是标题—— JUC.pdf

    wait()、notify()和notifyAll() 虚假唤醒 Condition 定制化通信 多线程锁 并发下的集合类 List Set Map Callable接口 线程创建的方式 callable / runnable FutureTask JUC常用辅助类 CountDownLatch (减少计数器) ...

    Java常见面试题208道.docx

    42.notify()和 notifyAll()有什么区别? 43.线程的 run()和 start()有什么区别? 44.创建线程池有哪几种方式? 45.线程池都有哪些状态? 46.线程池中 submit()和 execute()方法有什么区别? 47.在 java 程序中怎么...

    史上最全java面试,103项重点知识,带目录

    一、Java 基础 1 1. JDK 和 JRE 有什么区别? 1 2. == 和 equals 的区别是什么? 1 3. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗? 3 4. final 在 java 中有什么作用? 4 5. java 中的 Math.round...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    notify notifyAll 78 【多线程】sleep()和wait()分别是哪个类的方法,有什么区别? 79 【多线程】sleep()和yield()的区别 79 【多线程】对synchronized理解?用在代码块和方法上有什么区别? 80 【多线程】Volatile...

Global site tag (gtag.js) - Google Analytics