ReentrantLock

1.ReentrantLock概述

在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

2.ReentrantLock方法介紹

  •  int getQueueLength():返回正等待獲取此鎖定的線程估計數。
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個線程在等待獲取鎖線程

  • int getHoldCount():查詢當前線程保持此鎖定的個數,也就是調用lock()方法的次數。
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

  • boolean hasWaiters(Condition condition):查詢是否有線程正在等待與此鎖定有關的Condition條件。
  • int getWaitQueueLength(Condition condition):返回等待與此鎖定條件相關的給定條件Condition的線程估計數。
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同步

  •  boolean hasQueuedThread(Thread thread):查詢指定的線程是否正在等待獲取此鎖定。
  • boolean hasQueuedThreads():查詢是否有線程正在等待獲取此鎖定。
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

  • boolean isFair():判斷是否是公平鎖,ReentrantLock類默認使用的是非公平鎖。
  • boolean isHeldByCurrentThread():查詢當前線程是否保持此鎖定。
  • boolean isLocked():此鎖定是否由任意線程保持。
  • void lockInterruptibly():若是當前線程未被中斷,則獲取鎖定,若是已經被中斷則出現異常。
  • boolean tryLock():僅在調用時鎖定未被另外一個線程保持的狀況下,才獲取該鎖定。
  • boolean tryLock(long timeout, TimeUnit unit):若是鎖定在給定等待時間內沒有被另外一個線程保持,且當前線程未被中斷,則獲取該鎖定。
  • void awaitUninterruptibly():線程被中斷,不會拋出異常。
  • boolean awaitUntil(Date deadline):wait到某一個時間點,能夠被提早喚醒。

3.ReentrantReadWriteLock

  • readLock().lock();//獲取讀鎖
  • readLock().unlock();//釋放讀鎖
  • writeLock().lock();//獲取寫鎖
  • writeLock().unlock();//釋放寫鎖

讀讀共享,寫寫互斥,讀寫互斥,寫讀互斥。

相關文章
相關標籤/搜索