Lock+Condition 相对于 wait+notify 的一个优势案例分析

问题的描述

启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后是线程3打印11,12,13,14,15. 接着再由线程1打印16,17,18,19,20....以此类推, 直到打印到45.

wait+notify实现:

package com.tonyluis;
public class NumberPrintDemo {
	static int n = 1;
	static int state = 0;
	public static void main(String[] args) {
		new Thread(new MyThread(0)).start();
		new Thread(new MyThread(1)).start();
		new Thread(new MyThread(2)).start();
	}
}

class MyThread implements Runnable{
	private int state;
	MyThread(){
		this(0);
	}
	MyThread(int state){
		this.state=state;
	}
	public void run() {
		String threadName=Thread.currentThread().getName();
		for (int i = 0; i < 3; i++) {
			synchronized (MyThread.class) {
				while (state != NumberPrintDemo.state)
					try {
						MyThread.class.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				for (int j = 0; j < 5; j++)
					System.out.println(threadName+ ": " + NumberPrintDemo.n++);
				System.out.println();
				NumberPrintDemo.state++;
				NumberPrintDemo.state%=3;
				MyThread.class.notifyAll();
			}
		}
	}
}

 Lock+condition实现:

package com.tonyluis;
import java.util.concurrent.locks.*;
public class NumberPrint {
	static int state = 0;
	static int n = 1;
	static Lock lock = new ReentrantLock();
	static Condition condition[]=new Condition[3];
	public static void main(String[] args) {
		for(int i=0;i<condition.length;i++)
			condition[i]=lock.newCondition();
		NumberPrint np=new NumberPrint();
		
		new Thread(np.new MyThread(0)).start();
		new Thread(np.new MyThread(1)).start();
		new Thread(np.new MyThread(2)).start();
	}

class MyThread implements Runnable{
	private int state;
	MyThread(){
		this(0);
	}
	MyThread(int state){
		this.state=state;
	}
	public void run() {
		String threadName=Thread.currentThread().getName();
		for (int i = 0; i < 7; i++) {
			//不需要放到finnally{}中释放锁,因为后面await()会释放锁
				NumberPrint.lock.lock();
				while (state != NumberPrint.state)
					try {
						NumberPrint.condition[state].await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				for (int j = 0; j < 5; j++)
					System.out.println(threadName+ ": " + NumberPrint.n++);
				System.out.println();
				NumberPrint.state++;
				NumberPrint.state%=NumberPrint.condition.length;
				NumberPrint.condition[NumberPrint.state].signal();
				try {
					NumberPrint.condition[state].await();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

 

使用wait+notify的实现方式,在线程0进入notifyAll()方法之后,会唤醒线程1和线程2,线程1和线程2以及线程0会展开竞争,虽然最终是由线程1获得琐,过程可能比较曲折。

使用lock+condition的实现方法,线程0只会唤醒线程1,同时进入await()方法释放锁,这样只有线程1能够执行,非常的精确,尤其是并发量比较大的情况下。

posted @ 2016-06-13 18:14  TonyLuis  阅读(508)  评论(0编辑  收藏  举报