一、条件变量
条件变量实现了java.util.concurrent.locks.Condition接口,条件变量的实例化就是通过一个Lock对象上调用newCondition()方法获得的,这样条件就和一个锁绑定起来了。因此,Java中的条件变量只能和锁配合使用,来控制并发程序访问竞争资源的安全。
条件变量的出现是为了更精细的控制线程等待与唤醒,一个锁可以有多个条件,每个条件上有多个线程等待,通过await()方法,可以让线程在该条件下等待。当调用signalAll()方法时,又可以唤醒该条件下等待的线程。条件变量比较抽象,原因是它不是自然语言中的条件概念,而是控制程序的一种手段。
看个例子,有一个账户,多个用户(线程)在同时操作这个账户,有的存款有的取款,存款随便存,但取款有限制,不能透支,任何试图透支的操作都将等待里面有足够的存款时才执行操作。
CaseTest.java
1 package Thread; 2 import java.util.*; 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.locks.Condition; 6 import java.util.concurrent.locks.Lock; 7 import java.util.concurrent.locks.ReentrantLock; 8 public class CaseTest { 9 public static void main(String[] args){ 10 MyCount1 myCount1=new MyCount1("6516431",10000); 11 ExecutorService pool=Executors.newFixedThreadPool(2); 12 Thread t1=new SaveThread("张三",myCount1,2000); 13 Thread t2=new DrawThread("李四",myCount1,3600); 14 Thread t3=new SaveThread("王二",myCount1,2700); 15 Thread t4=new SaveThread("麻子",myCount1,600); 16 Thread t5=new DrawThread("胖子",myCount1,1300); 17 Thread t6=new DrawThread("小刘",myCount1,800); 18 pool.execute(t1); 19 pool.execute(t2); 20 pool.execute(t3); 21 pool.execute(t4); 22 pool.execute(t5); 23 pool.execute(t6); 24 pool.shutdown(); 25 } 26 } 27 class SaveThread extends Thread{ 28 private String name; 29 private MyCount1 myCount1; 30 private int x; 31 SaveThread(String name,MyCount1 myCount1,int x){ 32 this.name=name; 33 this.myCount1=myCount1; 34 this.x=x; 35 } 36 public void run(){ 37 myCount1.saving(x,name); 38 } 39 } 40 class DrawThread extends Thread{ 41 private String name; 42 private MyCount1 myCount; 43 private int x; 44 DrawThread(String name,MyCount1 myCount,int x){ 45 this.name=name; 46 this.myCount=myCount; 47 this.x=x; 48 } 49 public void run(){ 50 myCount.drawing(x,name); 51 } 52 } 53 class MyCount1{ 54 private String oid; 55 private int cash; 56 private Lock lock=new ReentrantLock(); 57 private Condition _save=lock.newCondition(); 58 private Condition _draw=lock.newCondition(); 59 MyCount1(String oid,int cash){ 60 this.oid=oid; 61 this.cash=cash; 62 } 63 public void saving(int x,String name){ 64 lock.lock(); //获取锁 65 if(x>0){ 66 cash+=x; 67 System.out.println(name+"存款"+x+",当前余额为:"+cash); 68 } 69 _draw.signalAll(); //唤醒所有等待线程。 70 lock.unlock(); //释放锁 71 } 72 public void drawing(int x,String name){ 73 lock.lock(); 74 try{ 75 if(cash-x<0){ 76 _draw.await();//阻塞取款操作 77 }else{ 78 cash-=x; 79 System.out.println(name+"取款"+x+",当前余额为:"+cash); 80 } 81 _save.signalAll();//唤醒所有存款操作 82 }catch(InterruptedException e){ 83 e.printStackTrace(); 84 }finally{ 85 lock.unlock(); 86 } 87 } 88 }