java并发编程(2)——wait和notify解析

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


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,可是这个仍是有顺序的,每一个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。其实启动等待对象链中各个线程的也是一个线程,在具体应用的时候,须要注意一下。
ide


应用实例:函数

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


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() {
				@Override
				public void run() {
					try {
						printAbc.printA(); // printA
					} catch (Exception e) {
						e.printStackTrace();
					}

				}
			}).start();

			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						printAbc.printB();// printB
					} catch (Exception e) {
						e.printStackTrace();
					}

				}
			}).start();

			new Thread(new Runnable() {
				@Override
				public 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();
	}
}


运行结果:spa

ABC操作系统

ABC线程

ABCcode

ABC对象

ABC进程

ABC

ABC

ABC

ABC

ABC

相关文章
相关标签/搜索