在java多線程中,能夠使用synchronized關鍵字來實現線程之間同步互斥,但在JDK1.5中增長了ReentrantLock也能達到一樣的效果,而且在擴展功能上也更增強大,並且使用上更加靈活。java
使用ReentrantLock實現生產者消費者:多線程
package chapter4.reentrant; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class MyStack { private List<String> list = new ArrayList<>(); ReentrantLock lock = new ReentrantLock(); Condition conditionp = lock.newCondition(); Condition conditionc = lock.newCondition(); public void push() { try { lock.lock(); while(list.size() == 1) { System.out.println("push 操做中的:"+Thread.currentThread().getName()+" 線程呈等待狀態"); conditionp.await(); } list.add("anything="+Math.random()); conditionc.signalAll(); System.out.println("push="+list.size()); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public void pop() { try { lock.lock(); while(list.size() == 0) { System.out.println("pop 操做中的:"+Thread.currentThread().getName()+" 線程呈等待狀態"); conditionc.await(); } String str = list.get(0); System.out.println("pop "+str); list.remove(0); conditionp.signalAll(); System.out.println("pop="+list.size()); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } package chapter4.reentrant; public class P { private MyStack myStack; public P(MyStack myStack) { this.myStack = myStack; } public void pushService() { myStack.push();; } } package chapter4.reentrant; public class C { private MyStack myStack; public C(MyStack myStack) { this.myStack = myStack; } public void popService() { myStack.pop();; } } package chapter4.reentrant; public class ThreadP extends Thread{ private P p; public ThreadP(P p) { this.p = p; } @Override public void run() { super.run(); p.pushService(); } } package chapter4.reentrant; public class ThreadC extends Thread{ private C c; public ThreadC(C c) { this.c = c; } @Override public void run() { super.run(); c.popService(); } } package chapter4.reentrant; public class Run { public static void main(String[] args) { try { int cnt=3; MyStack myStack = new MyStack(); P[] pArr = new P[cnt]; C[] cArr = new C[cnt]; for(int i=0;i<cnt;i++) { pArr[i] =new P(myStack); cArr[i] = new C(myStack);; } ThreadP[] threadPs = new ThreadP[cnt]; ThreadC[] threadCs = new ThreadC[cnt]; for(int i=0;i<cnt;i++) { threadPs[i] = new ThreadP(pArr[i]); threadCs[i] = new ThreadC(cArr[i]); } for(int i=0;i<cnt;i++) { threadCs[i].start(); } Thread.sleep(1000); for(int i=0;i<cnt;i++) { threadPs[i].start(); } } catch (InterruptedException e) { e.printStackTrace(); } } }
運行結果:dom
pop 操做中的:Thread-1 線程呈等待狀態
pop 操做中的:Thread-3 線程呈等待狀態
pop 操做中的:Thread-5 線程呈等待狀態
push=1
push 操做中的:Thread-2 線程呈等待狀態
push 操做中的:Thread-4 線程呈等待狀態
pop anything=0.04358985658650283
pop=0
pop 操做中的:Thread-3 線程呈等待狀態
pop 操做中的:Thread-5 線程呈等待狀態
push=1
push 操做中的:Thread-4 線程呈等待狀態
pop anything=0.8139775455313625
pop=0
pop 操做中的:Thread-5 線程呈等待狀態
push=1
pop anything=0.8443402579212704
pop=0ide
package chapter4.reentrantmethod; import java.util.concurrent.locks.ReentrantLock; public class Service { public ReentrantLock lock = new ReentrantLock(); public void method() { try { lock.lock(); System.out.println("ThreadName:"+Thread.currentThread().getName()+"進入方法!"); Thread.sleep(Integer.MAX_VALUE); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } package chapter4.reentrantmethod; public class Run { public static void main(String[] args) { try { final Service service = new Service(); Runnable runnable = new Runnable() { public void run() { service.method(); } }; Thread[] threads = new Thread[10]; for(int i=0;i<10;i++) { threads[i] = new Thread(runnable); } for(int i=0;i<10;i++) { threads[i].start(); } Thread.sleep(2000); System.out.println(service.lock.getQueueLength()+"個線程在等待獲取鎖"); } catch (Exception e) { e.printStackTrace(); } } }
運行結果:this
ThreadName:Thread-0進入方法!
9個線程在等待獲取鎖線程
package chapter4.reentrantmethod; import java.util.concurrent.locks.ReentrantLock; public class Service { public ReentrantLock lock = new ReentrantLock(); public void method1() { try { lock.lock(); System.out.println("method1 getHoldCount:"+lock.getHoldCount()); method2(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public void method2() { try { lock.lock(); System.out.println("method2 getHoldCount:"+lock.getHoldCount()); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } package chapter4.reentrantmethod; public class Run { public static void main(String[] args) { Service service = new Service(); service.method1(); } }
運行結果:blog
method1 getHoldCount:1
method2 getHoldCount:2rem
package chapter4.reentrantmethod; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Service { private ReentrantLock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void waitMethod() { try { lock.lock(); condition.await(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public void notifyMethod() { try { lock.lock();
System.out.println("是否有線程正在等待condition:"+lock.hasWaiters(condition)); System.out.println(lock.getWaitQueueLength(condition)+"個線程正在等待condition"); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } package chapter4.reentrantmethod; public class Run { public static void main(String[] args) { try { final Service service = new Service(); Runnable runnable = new Runnable() { public void run() { service.waitMethod(); } }; Thread[] threads = new Thread[10]; for(int i=0;i<10;i++) { threads[i] = new Thread(runnable); } for(int i=0;i<10;i++) { threads[i].start(); } Thread.sleep(2000); service.notifyMethod(); } catch (Exception e) { e.printStackTrace(); } } }
運行結果:get
是否有線程正在等待condition:true
10個線程正在等待condition同步
package chapter4.reentrantmethod; import java.util.concurrent.locks.ReentrantLock; public class Service2 { public ReentrantLock lock = new ReentrantLock(); public void waitMethod() { try { lock.lock(); Thread.sleep(Integer.MAX_VALUE); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } package chapter4.reentrantmethod; public class Run2 { public static void main(String[] args) { try { final Service2 service = new Service2(); Runnable runnable = new Runnable() { public void run() { service.waitMethod(); } }; Thread threada = new Thread(runnable); threada.start(); Thread.sleep(500); Thread threadb = new Thread(runnable); threadb.start(); Thread.sleep(500); System.out.println(service.lock.hasQueuedThread(threada)); System.out.println(service.lock.hasQueuedThread(threadb)); System.out.println(service.lock.hasQueuedThreads()); } catch (Exception e) { e.printStackTrace(); } } }
執行結果:
false
true
true
讀讀共享,寫寫互斥,讀寫互斥,寫讀互斥。