ReentrantReadWriteLock(讀寫鎖),父接口:ReadWriteLock。java
這個類 有2個鎖,一個是 讀操做鎖,另外一個是 寫操做鎖。使用讀操做鎖時能夠容許多個線程同時訪問,可是使用寫操做鎖時只容許一個線程進行。在一個線程執行寫操做時,其餘線程不可以執行讀操做。dom
讀寫鎖:分爲讀鎖和寫鎖,多個讀鎖不互斥,讀鎖與寫鎖互斥,這是由jvm本身控制的,你只要上好相應的鎖便可。若是你的代碼只讀數據,能夠不少人同時讀,但不能同時寫,那就上讀鎖;若是你的代碼修改數據,只能有一我的在寫,且不能同時讀取,那就上寫鎖。總之,讀的時候上讀鎖,寫的時候上寫鎖!jvm
import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.locks.ReentrantReadWriteLock; public class Queue3{ private int data = 0;//共享數據,只能有一個線程能寫該數據,但能夠有多個線程同時讀該數據。 private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); public void get(){ rwl.readLock().lock();//上讀鎖,其餘線程只能讀不能寫 System.out.println(sdf.format(new Date()) + " " + Thread.currentThread().getName() + " be ready to read data!"); try { Thread.sleep((long)(Math.random()*1000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(sdf.format(new Date()) + " " + Thread.currentThread().getName() + " have read data :" + data); rwl.readLock().unlock(); //釋放讀鎖,最好放在finnaly裏面 } public void put(int data){ rwl.writeLock().lock();//上寫鎖,不容許其餘線程讀也不容許寫 System.out.println(sdf.format(new Date()) + " " + Thread.currentThread().getName() + " be ready to write data!"); try { Thread.sleep((long)(Math.random()*1000)); } catch (InterruptedException e) { e.printStackTrace(); } this.data = data; System.out.println(sdf.format(new Date()) + " " + Thread.currentThread().getName() + " have write data: " + data); rwl.writeLock().unlock();//釋放寫鎖 } }
import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random; public class MyRunnable implements Runnable{ private int flat; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); private Queue3 queue3; Random random = new Random(); public MyRunnable(Queue3 queue3, int flat) { this.queue3 = queue3; this.flat = flat; } public void run() { if(flat == 0){ // 讀操做 queue3.get(); }else if(flat == 1){ // 寫操做 int data = random.nextInt(10); System.out.println(sdf.format(new Date()) + " " + Thread.currentThread().getName() + " 隨機數爲:" + data); queue3.put(data); }else{ System.out.println(sdf.format(new Date()) + " " + Thread.currentThread().getName() + "操做有誤!"); } } }
public class ReadWriteLockTest { public static void main(String[] args) { Queue3 queue3 = new Queue3(); MyRunnable myReader = new MyRunnable(queue3, 0); // 讀操做 MyRunnable myWriter = new MyRunnable(queue3, 1); // 寫操做 for(int i=0;i<3;i++){ Thread thread = new Thread(myReader); thread.start(); } Thread thread = new Thread(myWriter); thread.start(); } }
//console結果: 2017-09-08 03:56:35 Thread-1 be ready to read data! 2017-09-08 03:56:35 Thread-2 be ready to read data! 2017-09-08 03:56:35 Thread-0 be ready to read data! 2017-09-08 03:56:35 Thread-3 隨機數爲:6 2017-09-08 03:56:35 Thread-1 have read data :0 2017-09-08 03:56:35 Thread-2 have read data :0 2017-09-08 03:56:35 Thread-0 have read data :0 2017-09-08 03:56:35 Thread-3 be ready to write data! 2017-09-08 03:56:36 Thread-3 have write data: 6