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

本文介绍了Java中线程同步的基本概念,包括wait、notify及notifyAll方法的使用方式与注意事项。通过具体代码示例展示了如何利用这些方法实现线程间的互斥与协作。

       首先,调用一个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

   

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值