读写锁ReentrantReadWriteLock实例
当需要对集合同时进行写入和读取操作时,如果多线程同时操作会出现异常,那么现在利用ReadWriteLock显示锁,可以在写入量比较小,读取量比较大的场景中,方便的实现上述功能。
import java.util.Calendar; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * 可重入读写锁 */ @SuppressWarnings("all") public class ReadWriteLockDemo { private ReentrantReadWriteLock lock = null; // 读锁 private Lock readLock = null; // 写锁 private Lock writeLock = null; public int key = 100; public int index = 100; // 线程共享数据 public Map<Integer, String> dataMap = null; public ReadWriteLockDemo() { // 创建公平的可重入读写锁 lock = new ReentrantReadWriteLock(true); readLock = lock.readLock(); writeLock = lock.writeLock(); dataMap = new TreeMap<Integer, String>(); } public static void main(String[] args) { ReadWriteLockDemo test = new ReadWriteLockDemo(); // 第一次获取写入锁 test.writeLock.lock(); System.out.println("线程" + Thread.currentThread().getName() + "第一次获取写入锁"); // 第二次获取写入锁(这就是可重入的含义) test.writeLock.lock(); System.out.println("线程" + Thread.currentThread().getName() + "第二次获取写入锁"); test.readLock.lock(); System.out.println("线程" + Thread.currentThread().getName() + "第一次获取读取锁"); test.readLock.lock(); System.out.println("线程" + Thread.currentThread().getName() + "第二次获取读取锁"); test.readLock.lock(); System.out.println("线程" + Thread.currentThread().getName() + "第三次获取读取锁"); test.writeLock.unlock(); test.writeLock.unlock(); test.readLock.unlock(); test.readLock.unlock(); test.readLock.unlock(); test.test(); } public void test() { for (int i = 0; i < 10; i++) { new Thread(new reader(this)).start(); } for (int i = 0; i < 3; i++) { new Thread(new writer(this)).start(); } } public void read() { readLock.lock(); try { if (dataMap.isEmpty()) { Calendar now = Calendar.getInstance(); System.out.println("线程" + Thread.currentThread().getName() + "在" + now.getTime().getTime() + "读取数据,但是dataMap为空"); } String value = dataMap.get(index); Calendar now = Calendar.getInstance(); System.out.println("线程" + Thread.currentThread().getName() + "在" + now.getTime().getTime() + "读取数据,key=" + index + ",value=" + value + ",dataMap大小为" + dataMap.size()); if (value != null) { index++; } } finally { readLock.unlock(); } try { Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } } public void write() { writeLock.lock(); try { String value = "value" + key; dataMap.put(new Integer(key), value); Calendar now = Calendar.getInstance(); System.out.println("线程" + Thread.currentThread().getName() + "在" + now.getTime().getTime() + "写入数据,key=" + key + ",value=" + value + ",dataMap大小为" + dataMap.size()); key++; try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } } finally { writeLock.unlock(); } } class reader implements Runnable { private ReadWriteLockDemo test = null; public reader(ReadWriteLockDemo test) { this.test = test; } @Override public void run() { Calendar now = Calendar.getInstance(); System.out.println("读取线程" + Thread.currentThread().getName() + "在" + now.getTime().getTime() + "开始执行"); for (int i = 0; i < 10; i++) { test.read(); } } } class writer implements Runnable { private ReadWriteLockDemo test = null; public writer(ReadWriteLockDemo test) { this.test = test; } @Override public void run() { Calendar now = Calendar.getInstance(); System.out.println("写入线程" + Thread.currentThread().getName() + "在" + now.getTime().getTime() + "开始执行"); for (int i = 0; i < 10; i++) { test.write(); } } } }
运行结果:
线程main第一次获取写入锁 线程main第二次获取写入锁 线程main第一次获取读取锁 线程main第二次获取读取锁 线程main第三次获取读取锁 读取线程Thread-1在1339663449057开始执行 读取线程Thread-7在1339663449057开始执行 读取线程Thread-9在1339663449057开始执行 写入线程Thread-10在1339663449057开始执行 读取线程Thread-3在1339663449057开始执行 读取线程Thread-5在1339663449057开始执行 读取线程Thread-6在1339663449057开始执行 写入线程Thread-12在1339663449057开始执行 线程Thread-9在1339663449057读取数据,但是dataMap为空 读取线程Thread-0在1339663449057开始执行 写入线程Thread-11在1339663449057开始执行 读取线程Thread-2在1339663449057开始执行 线程Thread-7在1339663449057读取数据,但是dataMap为空 线程Thread-1在1339663449057读取数据,但是dataMap为空 读取线程Thread-8在1339663449057开始执行 读取线程Thread-4在1339663449057开始执行 线程Thread-7在1339663449072读取数据,key=100,value=null,dataMap大小为0 线程Thread-1在1339663449072读取数据,key=100,value=null,dataMap大小为0 线程Thread-9在1339663449072读取数据,key=100,value=null,dataMap大小为0 线程Thread-10在1339663449072写入数据,key=100,value=value100,dataMap大小为1 线程Thread-3在1339663449572读取数据,key=100,value=value100,dataMap大小为1 线程Thread-6在1339663449572读取数据,key=100,value=value100,dataMap大小为1 线程Thread-5在1339663449572读取数据,key=100,value=value100,dataMap大小为1 线程Thread-12在1339663449572写入数据,key=101,value=value101,dataMap大小为2 线程Thread-0在1339663450072读取数据,key=103,value=null,dataMap大小为2 线程Thread-11在1339663450072写入数据,key=102,value=value102,dataMap大小为3 线程Thread-2在1339663450572读取数据,key=103,value=null,dataMap大小为3 线程Thread-4在1339663450572读取数据,key=103,value=null,dataMap大小为3 线程Thread-8在1339663450572读取数据,key=103,value=null,dataMap大小为3 线程Thread-10在1339663450572写入数据,key=103,value=value103,dataMap大小为4 线程Thread-12在1339663451072写入数据,key=104,value=value104,dataMap大小为5 线程Thread-11在1339663451572写入数据,key=105,value=value105,dataMap大小为6 线程Thread-10在1339663452072写入数据,key=106,value=value106,dataMap大小为7 线程Thread-12在1339663452572写入数据,key=107,value=value107,dataMap大小为8 线程Thread-9在1339663453071读取数据,key=103,value=value103,dataMap大小为8 线程Thread-11在1339663453071写入数据,key=108,value=value108,dataMap大小为9 线程Thread-7在1339663453571读取数据,key=104,value=value104,dataMap大小为9 线程Thread-6在1339663453571读取数据,key=104,value=value104,dataMap大小为9 线程Thread-1在1339663453571读取数据,key=104,value=value104,dataMap大小为9 线程Thread-5在1339663453571读取数据,key=106,value=value105,dataMap大小为9 线程Thread-3在1339663453571读取数据,key=105,value=value104,dataMap大小为9 线程Thread-10在1339663453571写入数据,key=109,value=value109,dataMap大小为10 线程Thread-0在1339663454071读取数据,key=109,value=value109,dataMap大小为10 线程Thread-12在1339663454071写入数据,key=110,value=value110,dataMap大小为11 线程Thread-2在1339663454571读取数据,key=110,value=value110,dataMap大小为11 线程Thread-8在1339663454571读取数据,key=110,value=value110,dataMap大小为11 线程Thread-4在1339663454571读取数据,key=111,value=value110,dataMap大小为11 线程Thread-11在1339663454571写入数据,key=111,value=value111,dataMap大小为12 线程Thread-10在1339663455071写入数据,key=112,value=value112,dataMap大小为13 线程Thread-12在1339663455571写入数据,key=113,value=value113,dataMap大小为14 线程Thread-11在1339663456071写入数据,key=114,value=value114,dataMap大小为15 线程Thread-10在1339663456571写入数据,key=115,value=value115,dataMap大小为16 线程Thread-9在1339663457071读取数据,key=113,value=value113,dataMap大小为16 线程Thread-12在1339663457071写入数据,key=116,value=value116,dataMap大小为17 线程Thread-3在1339663457571读取数据,key=114,value=value114,dataMap大小为17 线程Thread-11在1339663457571写入数据,key=117,value=value117,dataMap大小为18 线程Thread-6在1339663458071读取数据,key=115,value=value115,dataMap大小为18 线程Thread-7在1339663458071读取数据,key=115,value=value115,dataMap大小为18 线程Thread-5在1339663458071读取数据,key=116,value=value115,dataMap大小为18 线程Thread-0在1339663458071读取数据,key=117,value=value116,dataMap大小为18 线程Thread-1在1339663458071读取数据,key=117,value=value116,dataMap大小为18 线程Thread-10在1339663458071写入数据,key=118,value=value118,dataMap大小为19 线程Thread-8在1339663458571读取数据,key=120,value=null,dataMap大小为19 线程Thread-12在1339663458571写入数据,key=119,value=value119,dataMap大小为20 线程Thread-2在1339663459070读取数据,key=120,value=null,dataMap大小为20 线程Thread-4在1339663459070读取数据,key=120,value=null,dataMap大小为20 线程Thread-11在1339663459070写入数据,key=120,value=value120,dataMap大小为21 线程Thread-10在1339663459570写入数据,key=121,value=value121,dataMap大小为22 线程Thread-12在1339663460070写入数据,key=122,value=value122,dataMap大小为23 线程Thread-11在1339663460570写入数据,key=123,value=value123,dataMap大小为24 线程Thread-9在1339663461070读取数据,key=120,value=value120,dataMap大小为24 线程Thread-10在1339663461070写入数据,key=124,value=value124,dataMap大小为25 线程Thread-12在1339663461570写入数据,key=125,value=value125,dataMap大小为26 线程Thread-3在1339663462070读取数据,key=121,value=value121,dataMap大小为26 线程Thread-7在1339663462070读取数据,key=121,value=value121,dataMap大小为26 线程Thread-1在1339663462070读取数据,key=122,value=value122,dataMap大小为26 线程Thread-6在1339663462070读取数据,key=121,value=value121,dataMap大小为26 线程Thread-0在1339663462070读取数据,key=122,value=value121,dataMap大小为26 线程Thread-5在1339663462070读取数据,key=122,value=value121,dataMap大小为26 线程Thread-11在1339663462070写入数据,key=126,value=value126,dataMap大小为27 线程Thread-8在1339663462570读取数据,key=127,value=null,dataMap大小为27 线程Thread-10在1339663462570写入数据,key=127,value=value127,dataMap大小为28 线程Thread-2在1339663463070读取数据,key=127,value=value127,dataMap大小为28 线程Thread-4在1339663463070读取数据,key=127,value=value127,dataMap大小为28 线程Thread-12在1339663463070写入数据,key=128,value=value128,dataMap大小为29 线程Thread-11在1339663463570写入数据,key=129,value=value129,dataMap大小为30 线程Thread-9在1339663464070读取数据,key=129,value=value129,dataMap大小为30 线程Thread-0在1339663465069读取数据,key=130,value=null,dataMap大小为30 线程Thread-1在1339663465069读取数据,key=130,value=null,dataMap大小为30 线程Thread-7在1339663465069读取数据,key=130,value=null,dataMap大小为30 线程Thread-5在1339663465069读取数据,key=130,value=null,dataMap大小为30 线程Thread-3在1339663465069读取数据,key=130,value=null,dataMap大小为30 线程Thread-6在1339663465069读取数据,key=130,value=null,dataMap大小为30 线程Thread-8在1339663465569读取数据,key=130,value=null,dataMap大小为30 线程Thread-4在1339663466069读取数据,key=130,value=null,dataMap大小为30 线程Thread-2在1339663466069读取数据,key=130,value=null,dataMap大小为30 线程Thread-9在1339663467069读取数据,key=130,value=null,dataMap大小为30 线程Thread-7在1339663468069读取数据,key=130,value=null,dataMap大小为30 线程Thread-3在1339663468069读取数据,key=130,value=null,dataMap大小为30 线程Thread-1在1339663468069读取数据,key=130,value=null,dataMap大小为30 线程Thread-0在1339663468069读取数据,key=130,value=null,dataMap大小为30 线程Thread-6在1339663468069读取数据,key=130,value=null,dataMap大小为30 线程Thread-5在1339663468069读取数据,key=130,value=null,dataMap大小为30 线程Thread-8在1339663468569读取数据,key=130,value=null,dataMap大小为30 线程Thread-4在1339663469069读取数据,key=130,value=null,dataMap大小为30 线程Thread-2在1339663469069读取数据,key=130,value=null,dataMap大小为30 线程Thread-9在1339663470069读取数据,key=130,value=null,dataMap大小为30 线程Thread-0在1339663471068读取数据,key=130,value=null,dataMap大小为30 线程Thread-1在1339663471068读取数据,key=130,value=null,dataMap大小为30 线程Thread-3在1339663471068读取数据,key=130,value=null,dataMap大小为30 线程Thread-7在1339663471068读取数据,key=130,value=null,dataMap大小为30 线程Thread-6在1339663471068读取数据,key=130,value=null,dataMap大小为30 线程Thread-5在1339663471068读取数据,key=130,value=null,dataMap大小为30 线程Thread-8在1339663471568读取数据,key=130,value=null,dataMap大小为30 线程Thread-2在1339663472068读取数据,key=130,value=null,dataMap大小为30 线程Thread-4在1339663472068读取数据,key=130,value=null,dataMap大小为30 线程Thread-9在1339663473068读取数据,key=130,value=null,dataMap大小为30 线程Thread-0在1339663474068读取数据,key=130,value=null,dataMap大小为30 线程Thread-1在1339663474068读取数据,key=130,value=null,dataMap大小为30 线程Thread-3在1339663474068读取数据,key=130,value=null,dataMap大小为30 线程Thread-6在1339663474068读取数据,key=130,value=null,dataMap大小为30 线程Thread-5在1339663474068读取数据,key=130,value=null,dataMap大小为30 线程Thread-7在1339663474068读取数据,key=130,value=null,dataMap大小为30 线程Thread-8在1339663474568读取数据,key=130,value=null,dataMap大小为30 线程Thread-2在1339663475068读取数据,key=130,value=null,dataMap大小为30 线程Thread-4在1339663475068读取数据,key=130,value=null,dataMap大小为30 线程Thread-9在1339663476067读取数据,key=130,value=null,dataMap大小为30 线程Thread-6在1339663477067读取数据,key=130,value=null,dataMap大小为30 线程Thread-7在1339663477067读取数据,key=130,value=null,dataMap大小为30 线程Thread-0在1339663477067读取数据,key=130,value=null,dataMap大小为30 线程Thread-1在1339663477067读取数据,key=130,value=null,dataMap大小为30 线程Thread-3在1339663477067读取数据,key=130,value=null,dataMap大小为30 线程Thread-5在1339663477067读取数据,key=130,value=null,dataMap大小为30 线程Thread-8在1339663477567读取数据,key=130,value=null,dataMap大小为30 线程Thread-2在1339663478067读取数据,key=130,value=null,dataMap大小为30 线程Thread-4在1339663478067读取数据,key=130,value=null,dataMap大小为30 线程Thread-9在1339663479067读取数据,key=130,value=null,dataMap大小为30 线程Thread-0在1339663480067读取数据,key=130,value=null,dataMap大小为30 线程Thread-5在1339663480067读取数据,key=130,value=null,dataMap大小为30 线程Thread-1在1339663480067读取数据,key=130,value=null,dataMap大小为30 线程Thread-3在1339663480067读取数据,key=130,value=null,dataMap大小为30 线程Thread-6在1339663480067读取数据,key=130,value=null,dataMap大小为30 线程Thread-7在1339663480067读取数据,key=130,value=null,dataMap大小为30 线程Thread-8在1339663480567读取数据,key=130,value=null,dataMap大小为30 线程Thread-4在1339663481067读取数据,key=130,value=null,dataMap大小为30 线程Thread-2在1339663481067读取数据,key=130,value=null,dataMap大小为30