使用condition對象能夠對線程業務進行規劃和排序。請看以下代碼java
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Run { 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 thread = new Thread() { @Override public void run() { super.run(); try { lock.lock(); while (nextPrintWho != 1) { conditionA.await(); } for (int i = 0; i < 3; i++) { System.out.println("printA is " + i); } nextPrintWho = 2; conditionB.signalAll(); } catch (InterruptedException ex) { ex.printStackTrace(); } finally { lock.unlock(); } } }; Thread threadb = new Thread() { @Override public void run() { super.run(); try { lock.lock(); while (nextPrintWho != 2) { conditionB.await(); } for (int i = 0; i < 3; i++) { System.out.println("printB is " + i); } nextPrintWho = 3; conditionC.signalAll(); } catch (InterruptedException ex) { ex.printStackTrace(); } finally { lock.unlock(); } } }; Thread threadc = new Thread() { @Override public void run() { super.run(); try { lock.lock(); while (nextPrintWho != 3) { conditionC.await(); } for (int i = 0; i < 3; i++) { System.out.println("printC is " + i); } nextPrintWho = 1; conditionB.signalAll(); } catch (InterruptedException ex) { ex.printStackTrace(); } finally { lock.unlock(); } } }; Thread[] aArray = new Thread[10]; Thread[] bArray = new Thread[10]; Thread[] cArray = new Thread[10]; for (int i =0 ;i <5 ;i++) { aArray[i] = new Thread(thread); bArray[i] = new Thread(threadb); cArray[i] = new Thread(threadc); aArray[i].start(); bArray[i].start(); cArray[i].start(); } } }
輸出結果安全
printA is 0 printA is 1 printA is 2 printB is 0 printB is 1 printB is 2 printC is 0 printC is 1 printC is 2 printA is 0 printA is 1 printA is 2 printB is 0 printB is 1 printB is 2 printC is 0 printC is 1 printC is 2 printA is 0 printA is 1 printA is 2 printB is 0 printB is 1 printB is 2 printC is 0 printC is 1 printC is 2
ReentrantLock鎖是徹底互斥的鎖,即同一時間內只有一個線程執行鎖後面的方法,這樣作雖然保證了變量的線程安全性,可是效果是很是低下的。因此jdk提供了一種讀寫鎖,在某些不須要操做gong共享變量的狀況下徹底能夠使用讀寫鎖來提高方法的運行速度。ide
讀寫鎖包含了兩個鎖,一個是讀鎖,也稱共享鎖,一個是寫鎖,也稱排他鎖。即多個讀鎖之間不互斥,寫鎖和讀鎖互斥,讀鎖和讀鎖互斥。在沒有線程執行寫入操做的時候,進行讀取操做的多個線程均可以獲取讀鎖,寫鎖只有在得到鎖後才能進行寫操做。this
請看以下代碼線程
public class ReadLock { private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); public void read() { try { readWriteLock.readLock().lock(); System.out.println("得到鎖---->線程名稱是---->"+Thread.currentThread().getName()); Thread.sleep(1000); System.out.println("睡眠甦醒---->線程名稱是---->"+Thread.currentThread().getName()); } catch (InterruptedException ex){ ex.printStackTrace(); }finally { readWriteLock.readLock().unlock(); } } } public class ThreadA extends Thread{ private ReadLock readLock ; public ThreadA(ReadLock readLock) { this.readLock = readLock; } @Override public void run() { readLock.read(); } } public class ThreadB extends Thread{ private ReadLock readLock ; public ThreadB(ReadLock readLock) { this.readLock = readLock; } @Override public void run() { readLock.read(); } } public class Run { public static void main(String[] args) { ReadLock lock = new ReadLock(); ThreadA threadA = new ThreadA(lock); threadA.setName("A"); ThreadB threadB = new ThreadB(lock); threadB.setName("B"); threadA.start(); threadB.start(); } }
輸出結果是code
得到鎖---->線程名稱是---->B 得到鎖---->線程名稱是---->A 睡眠甦醒---->線程名稱是---->B 睡眠甦醒---->線程名稱是---->A
稍微修改上面的代碼對象
public class WriteLock { private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); public void read() { try { readWriteLock.writeLock().lock(); System.out.println("得到鎖---->線程名稱是---->"+Thread.currentThread().getName()); Thread.sleep(1000); System.out.println("睡眠甦醒---->線程名稱是---->"+Thread.currentThread().getName()); } catch (InterruptedException ex){ ex.printStackTrace(); }finally { readWriteLock.writeLock().unlock(); } } }
輸出結果排序
得到鎖---->線程名稱是---->A 睡眠甦醒---->線程名稱是---->A 得到鎖---->線程名稱是---->B 睡眠甦醒---->線程名稱是---->B
請參考以下代碼get
import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLock { private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); public void read() { try { readWriteLock.readLock().lock(); System.out.println("讀線程得到鎖---->線程名稱是---->" + Thread.currentThread().getName()); Thread.sleep(1000); System.out.println("讀線程睡眠甦醒---->線程名稱是---->" + Thread.currentThread().getName()); } catch (InterruptedException ex) { ex.printStackTrace(); } finally { readWriteLock.readLock().unlock(); } } public void write() { try { readWriteLock.writeLock().lock(); System.out.println("寫線程得到鎖---->線程名稱是---->" + Thread.currentThread().getName()); Thread.sleep(1000); System.out.println("寫線程睡眠甦醒---->線程名稱是---->" + Thread.currentThread().getName()); } catch (InterruptedException ex) { ex.printStackTrace(); } finally { readWriteLock.writeLock().unlock(); } } } public class ThreadA extends Thread{ private ReadWriteLock readLock ; public ThreadA(ReadWriteLock readLock) { this.readLock = readLock; } @Override public void run() { readLock.read(); } } public class ThreadB extends Thread{ private ReadWriteLock readLock ; public ThreadB(ReadWriteLock readLock) { this.readLock = readLock; } @Override public void run() { readLock.write(); } } public class Run { public static void main(String[] args) { ReadWriteLock lock = new ReadWriteLock(); ThreadA threadA = new ThreadA(lock); threadA.setName("A"); ThreadB threadB = new ThreadB(lock); threadB.setName("B"); threadA.start(); threadB.start(); } }
輸出結果it
讀線程得到鎖---->線程名稱是---->A 讀線程睡眠甦醒---->線程名稱是---->A 寫線程得到鎖---->線程名稱是---->B 寫線程睡眠甦醒---->線程名稱是---->B