1.Lock的使用java
private Lock lock = new ReentrantLock(); public void test(){ lock.lock(); System.out.println("#######"); lock.unlock(); }
注意:try-catch-finally結合使用,unlock()在finally裏面。ide
2.使用condition實現等待/通知spa
關鍵字synchronized與wait()和notify()/notifyAll()方法相結合能夠實現等待/通知模式,類ReentrantLock也能夠實現一樣的功能,但須要藉助Condition對象。能夠實現多路通知功能,也就是在一個Lock對象裏面能夠建立多個Condition實例,線程對象能夠註冊在指定Condition中,從而能夠有選擇性進行線程通知,在調度線程上更加靈活。線程
synchronized的wait()和notify(),而Condition對象,卻能夠選擇性通知。code
2.1 使用condition API對象
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class test5 { private Lock lock = new ReentrantLock(); public Condition condition1 = lock.newCondition(); public Condition condition2 = lock.newCondition(); public void awaitA(){ try { lock.lock(); System.out.println("A等待"); condition1.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ lock.unlock(); } } public void awaitB(){ try { lock.lock(); System.out.println("B等待"); condition2.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ lock.unlock(); } } public void signalA(){ try { lock.lock(); System.out.println("通知a"); condition1.signalAll(); } finally { lock.unlock(); } // TODO: handle finally clause } public void signalB(){ try { lock.lock(); System.out.println("通知B"); condition2.signalAll(); } finally { lock.unlock(); } // TODO: handle finally clause } public static void main(String[] args) { test5 t5 = new test5(); //建立兩個線程 // Thread thread1= new Thread(t5); //Thread thread2= new Thread(t5); //只通知線程1 // t5.signalA(); } }
2.二、生產者與消費模式:交替打印get
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class test6 { private Lock lock =new ReentrantLock(); private Condition condition= lock.newCondition(); private boolean hasValue= false; public void set(){ try { lock.lock(); while(hasValue == true){ condition.await(); } System.out.println("@@@"); hasValue= true; condition.signal(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } public void get(){ try { lock.lock(); while(hasValue == false){ condition.await(); } System.out.println("###"); hasValue= false; condition.signal(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } public static void main(String[] args) { test6 test6 = new test6(); //建立兩個線程 //啓動 } }
注意:多消費者和多生產者,使用condition.signalAll();it
3.公平鎖與非公平鎖io
鎖Lock分爲「公平鎖」和「非公平鎖」,公平鎖表示線程獲取的順序是按照線程加鎖的順序來分配的,即先來得的FIFO先進先出的順序。而非公平鎖就是一種獲取搶佔機制,是隨機得到鎖的,和公平鎖不同就是先來得不必定先獲得鎖,這個方式可能形成某些線程一直拿不到鎖,結果也就是不公平的了。class
import java.util.concurrent.locks.ReentrantLock; public class test7 { private ReentrantLock lock; public test7(boolean isFair){//傳入true表示公平鎖,反之爲非公平鎖 super(); lock = new ReentrantLock(); } public void add(){ try { lock.lock(); } finally { lock.unlock(); } } }
4.API講解
4.一、方法lockInterruptibly()
該方法的做用是:若是當前線程未被中斷,則獲取鎖定,若是已經被中斷則拋出異常。
4.二、tryLock()
改方法的做用是:僅在調用時鎖定未被另外一個線程保持的狀況下,才獲取該鎖。
private Lock lock = new ReentrantLock(); public void test(){ if(lock.tryLock()){ System.out.println("#######"); } }
同時,tryLock(long timeout,TimeUnit unit)的做用是,若是鎖定在給等待時間內沒有被另外一個線程保持,且當前線程未被中斷,則獲取該鎖定。
4.三、使用Condition實現順序執行
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class test8 { volatile private static int nextPrintWho =1; private static ReentrantLock lock = new ReentrantLock(); final private static Condition conditionA = lock.newCondition(); final private static Condition conditionB = lock.newCondition(); final private static Condition conditionC = lock.newCondition(); public static void main(String[] args) { Thread threadA = new Thread(){ @Override public void run() { try { lock.lock(); while(nextPrintWho != 1){ conditionA.await(); } for(int i=1; i<4;i++){ System.out.println("ThreadA"+i); } nextPrintWho = 2; conditionB.signalAll(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } }; Thread threadB = new Thread(){ @Override public void run() { try { lock.lock(); while(nextPrintWho != 2){ conditionB.await(); } for(int i=1; i<4;i++){ System.out.println("ThreadB"+i); } nextPrintWho = 3; conditionC.signalAll(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } }; Thread threadC = new Thread(){ @Override public void run() { try { lock.lock(); while(nextPrintWho != 3){ conditionC.await(); } for(int i=1; i<4;i++){ System.out.println("ThreadC"+i); } nextPrintWho = 1; conditionA.signalAll(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } }; Thread[] aAray =new Thread[5]; Thread[] bAray =new Thread[5]; Thread[] cAray =new Thread[5]; for(int i=0;i<5;i++){ aAray[i] =new Thread(threadA); bAray[i] =new Thread(threadB); cAray[i] =new Thread(threadC); aAray[i].start(); bAray[i].start(); cAray[i].start(); } } }
總結:實現線程的順序執行,可使用:join方法,也可使用Condition。
5.使用ReentrantReadWriteLock類
讀寫鎖表示有兩個鎖,一個是讀操做相關的鎖,也稱爲共享鎖;另外一個是寫操做相關的的鎖,也叫排它鎖。也就是多個讀鎖之間不互斥,讀鎖與寫鎖互斥,寫鎖與寫鎖互斥。在沒有線程進行寫入操做時,進行讀取操做的多個線程均可以獲取鎖,而進行寫入的操做的線程只有在獲取寫鎖後才能進行操做。即多個線程能夠同時進行讀取操做,可是同一時刻只容許一個線程進行寫入操做。
import java.util.concurrent.locks.ReentrantReadWriteLock; public class test9 { private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public void read(){ try { lock.readLock(); } catch (Exception e) { // TODO: handle exception }finally { lock.readLock().unlock(); } } public void wirte(){ try { lock.writeLock(); } catch (Exception e) { // TODO: handle exception }finally { lock.writeLock().unlock(); } } }