上一篇文章讲了使用synchronized关键字实现线程的生产者/消费者模式,今天将贴上另一种实现方式:Lock+Condition,这好像是JDK1.5以后的新特性,需要导入java.util.concurrent并发包。主要是用Lock代替了synchronized关键字,Condition里的await()、signal()、signalAll()代替了原来Object的wait()、notify()、notifyall()方法。下面请看代码(基于上一篇文章代码修改d):
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * java线程协作,生产者/消费者 * 使用java.util.concurrent并发包,引入更高级的Lock锁机制 * @author 李小拐 * 2016年6月21日14:23:09 */ public class Plate { private Lock lock=new ReentrantLock();//Lock代替旧版的synchronized private Condition condition=lock.newCondition();//Condition代替旧版的Object监视器 private static int plate=0;//声明一个变量,代表盘子,可以放入和拿出 //放入一个苹果 public /*synchronized*/ void putApple() throws InterruptedException { lock.lock(); try{ while (plate==1) { //this.wait();//如果有苹果,不能再放了,就等待 condition.await(); } System.out.println("放入apple"); plate=1; //this.notifyAll();//放入后,唤醒等待的线程 condition.signalAll(); }finally{ lock.unlock();//需要手动释放锁 } } //拿出一个苹果 public /*synchronized*/ void getApple() throws InterruptedException { lock.lock(); try{ while (plate==0) { //this.wait();//如果盘子为空,则不能取,等待放入苹果才能取 condition.await(); } System.out.println("拿出苹果"); plate=0; //this.notifyAll();//取出后,唤醒等待线程 condition.signalAll(); }finally{ lock.unlock();//需要手动释放锁 } } public static void main(String[] args) { Plate plate=new Plate(); for (int i = 0; i < 200; i++) {//put和get各执行20次 new getApple(plate).start(); new putApple(plate).start(); } } } //拿出苹果的线程 class getApple extends Thread{ private Plate plate; public getApple(Plate plate) { this.plate=plate; } @Override public void run() { try { plate.getApple(); } catch (InterruptedException e) { e.printStackTrace(); } } } //放入苹果的线程 class putApple extends Thread{ private Plate plate; public putApple(Plate plate) { this.plate=plate; } @Override public void run() { try { plate.putApple(); } catch (InterruptedException e) { e.printStackTrace(); } } }
从上面代码来看,好像Lock和Condition相比于synchronized并没有体现出什么优势。那么接下来请继续看代码,使用Lock和Condition实现上一篇文章中多线程打印ABCD的功能(原代码基础上面修改):
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 生产者/消费者 :顺序打印ABCD condition实现 * @author 李小拐 * 2016年6月20日21:00:36 */ public class PrintABCD { /** * @param args */ public static void main(String[] args) { //一定是在这里new一个对象,不能再线程里面new,否则多个线程就不是操作的同一个内存对象 PrintABCD abcd=new PrintABCD(); for (int i = 0; i < 10; i++) { (new printA(abcd)).start(); (new printB(abcd)).start(); (new printC(abcd)).start(); (new printD(abcd)).start(); } } //为不同的线程创建不同的锁 private Lock lock=new ReentrantLock(); private Condition conditionA=lock.newCondition(); private Condition conditionB=lock.newCondition(); private Condition conditionC=lock.newCondition(); private Condition conditionD=lock.newCondition(); private static int who=1;//用变量who来控制要打印的值;1,2,3,4分别代表A,B,C,D public /*synchronized*/ void printA() throws InterruptedException { lock.lock(); try{ while (who!=1) { //this.wait();//不等于1就等待,等于1的时候才执行 conditionA.await();//指定A线程等待 } System.out.println("A"); who=2;//A的下一状态B //this.notifyAll(); conditionB.signal();//直接指明唤醒B线程,这就是condition相比synchronized的强大之处 }finally{ lock.unlock(); } } public /*synchronized*/ void printB() throws InterruptedException { lock.lock(); try{ while (who!=2) { //this.wait(); conditionB.await(); } System.out.println("--B"); who=3;//B的下一状态C //this.notifyAll(); conditionC.signal(); }finally{ lock.unlock(); } } public /*synchronized*/ void printC() throws InterruptedException { lock.lock(); try{ while (who!=3) { //this.wait(); conditionC.await(); } System.out.println("----C"); who=4;//C的下一状态D //this.notifyAll(); conditionD.signal(); }finally{ lock.unlock(); } } public /*synchronized*/ void printD() throws InterruptedException { lock.lock(); try{ while (who!=4) { //this.wait(); conditionD.await(); } System.out.println("------D"); who=1;//D的下一状态A //this.notifyAll(); conditionA.signal(); }finally{ lock.unlock(); } } } //四个线程,分别打印ABCD class printA extends Thread{ PrintABCD p; printA(PrintABCD p){ this.p=p; } @Override public void run() { try { p.printA(); } catch (InterruptedException e) { e.printStackTrace(); } } } class printB extends Thread{ PrintABCD p; printB(PrintABCD p){ this.p=p; } @Override public void run() { try { p.printB(); } catch (InterruptedException e) { e.printStackTrace(); } } } class printC extends Thread{ PrintABCD p; printC(PrintABCD p){ this.p=p; } @Override public void run() { try { p.printC(); } catch (InterruptedException e) { e.printStackTrace(); } } } class printD extends Thread{ PrintABCD p; printD(PrintABCD p){ this.p=p; } @Override public void run() { try { p.printD(); } catch (InterruptedException e) { e.printStackTrace(); } } }
本文若有不足之处,还望大神些不吝赐教,及时指出!