標籤:
如果程式不使用synchronized關鍵字來保證同步時,而是直接使用Lock對象來保證同步,則系統中不存在隱式的同步監視器,也就不能使用wait()、notify()、notifyAll()方法進行通訊了。
當使用Lock對象來保證同步時,java提供了一個Condition類來保持協調,使用Condition可以讓哪些已經得到的Lock對象卻無法繼續執行的線程釋放Lock對象,Condition對象也可以喚醒其他處於等待的線程。
Condition將同步監視器方法(wait()、notify()、和notifyAll())分解成截然不同的對象,以便通過將這些對象與Lock對象組合使用,為每個對象提供多個等待集(wait-set)。在這種情況下,Lock替代了同步方法或同步代碼塊,Condition替代了同步監視器的功能。
Condition執行個體被綁定在一個Lock對象上,要獲得特定的Lock執行個體的Condition執行個體,調用Lock對象的newCondition()方法即可。Condition類提供了如下3個方法。
1、await():類似於隱式同步監視器上的wait()方法,導致當前線程等待,知道其他線程調用該Condition 的signal()方法或signalAll()方法來喚醒該線程,該await()方法有更多的變體,如long awaitNanos(long nanosTimeout)、void awaitUninterruptibly()、awaitUntil(Data deadline)等,可以完成豐富的等待操作。
2、signal():喚醒在此Lock對象上等待的單個線程,如果所有線程都在該Lock對象上等待,則會選擇喚醒其中一個線程,選擇是任意性的,只有當前線程放棄對Lock對象的鎖定後(使用await()方法),才可以執行被喚醒的線程。
3、signalAll():喚醒在此Lock對象上等待的所有線程,只有當前線程放棄對該對象Lock對象的鎖定後,才可以執行被喚醒的線程。
1 import java.util.concurrent.locks.Condition; 2 import java.util.concurrent.locks.ReentrantLock; 3 public class ConditionClass{ 4 public static void main(String[] args){ 5 Account a=new Account("1",100000); 6 ThreadClass t=new ThreadClass(a,1000,"NO1"); 7 new Thread(new RunnableClass(a,500)).start(); 8 new Thread(new RunnableClass(a,500)).start(); 9 new Thread(new RunnableClass(a,500)).start();10 }11 }12 class Account{13 //顯示定義的Lock對象14 private final ReentrantLock lock=new ReentrantLock();15 //獲得指定Lock對象對應的Condition16 private final Condition cond=lock.newCondition();17 private String name;18 private double money;19 private boolean flag=false;20 public Account(String name,double money){21 this.name=name;22 this.money=money;23 }24 public double getMoney(){25 return money;26 }27 public void make(double dymoney){28 lock.lock();29 try{30 if(!flag){ 31 System.out.println(Thread.currentThread().getName()+"儲存了:"+dymoney);32 money+=dymoney;33 System.out.println("現在餘額為:"+money);34 flag=true;35 cond.signalAll();36 }else{37 cond.await();38 }39 }catch(Exception e){System.out.println(e);}finally{40 lock.unlock();41 }42 }43 public void take(double dymoney){44 lock.lock();45 try{46 if(flag){47 System.out.println(Thread.currentThread().getName()+"取走了:"+dymoney);48 money-=dymoney;49 flag=false;50 System.out.println("現在餘額為:"+money);51 cond.signalAll();52 }else{53 cond.await();54 }55 }catch(Exception e){56 System.out.println(e);57 }finally{58 lock.unlock();59 }60 }61 }62 class ThreadClass extends Thread{63 private Account account;64 private double dymoney;65 private String name;66 public ThreadClass(Account account,double dymoney,String name){67 super(name);68 this.account=account;69 this.dymoney=dymoney;70 start();71 }72 public void run(){73 for(int i=0;i<100;i++){74 account.make(dymoney);75 }76 }77 78 }79 class RunnableClass implements Runnable{80 private Account account;81 private double dymoney;82 public RunnableClass(Account account,double dymoney){83 this.account=account;84 this.dymoney=dymoney;85 }86 public void run(){87 for(int k=0;k<100;k++){88 try{89 Thread.sleep(1000);90 account.take(dymoney);91 }catch(Exception e){}92 }93 }94 }
顯示地使用Lock對象來充當同步監視器,則需要使用Condition對象來暫停、喚醒 指定的線程。
java中使用Condition控制線程通訊(java瘋狂講義)