博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
黑马程序员-读写锁和缓存类
阅读量:7222 次
发布时间:2019-06-29

本文共 7790 字,大约阅读时间需要 25 分钟。

------- android培训java培训期待与您交流 ----------

 

读写锁:

   分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,也就是说可以多个线程在读取数据,不能一边在读取数据一边在写入数据,也不能一个线程在写另一个线程也在写,保证了数据的完整性。

创建读写锁:

  ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

设置、释放读写锁:

  rwl.readLock().lock(); 设置读锁

  rwl.readLock().unlock(); 释放读锁

  rwl.writeLock().lock();设置写锁

  rwl.writeLock().unlock(); 释放写锁

注意:释放锁的操作必须放到finally中,即使前面的代码发生异常也要释放资源。

1     public static void main(String[] args) { 2         // 创建线程数固定为5的线程池 3         ExecutorService threadPool = Executors.newFixedThreadPool(5); 4         //内部类在局部时只能访问被final修饰的局部变量 5         final ReadWrite rw = new ReadWrite(); 6         for (int i = 0; i < 10; i++) { 7             //内部类在局部时只能访问被final修饰的局部变量 8             final int num = i; 9             //添加任务10             threadPool.execute(new Runnable() {11                 12                 @Override13                 public void run() {14                     //交替执行读写操作15                     if (num % 2 == 0) {16                         rw.write("ssssss");17                     }else{18                         rw.read();19                     }20                 }21             });22         }23     }24 25     static class ReadWrite {26         private String value;27         // 创建读写锁28         private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();29 30         // 读31         public void read() {32             //设置读锁33             rwl.readLock().lock();34             try {35                 36                 System.out.println(Thread.currentThread().getName() + "read data ");37                 System.out.println(value);38                 System.out.println("end read data");39             } finally {40                 41                 //释放读锁42                 //释放锁操作一定要放在finally中,因为前面有可能发生异常,如果没放在finally中就不能释放资源43                 rwl.readLock().unlock();44             }45         }46 47         // 写48         public void write(String num) {49             //设置写锁50             rwl.writeLock().lock();51             try {52                 System.out.println(Thread.currentThread().getName() +"write data begin!");53                 Thread.sleep(10);54                 value = num;55                 System.out.println(Thread.currentThread().getName() +"write data ........end!");56             }catch(Exception e){57                 58             } finally {59                 //释放写锁60                 rwl.writeLock().unlock();61             }62         }63     }

 

缓存类

1 package cn.itcst.day5; 2  3 import java.util.HashMap; 4 import java.util.Map; 5 import java.util.concurrent.ExecutorService; 6 import java.util.concurrent.Executors; 7 import java.util.concurrent.locks.ReadWriteLock; 8 import java.util.concurrent.locks.ReentrantReadWriteLock; 9 10 /**11  * 缓存类12  * 13  * @author Administrator14  * 15  */16 public class CacheDemo {17 18     public static void main(String[] args) {19         // TODO Auto-generated method stub20         //创建线程池21         ExecutorService threadPool = Executors.newFixedThreadPool(3);22         for (int i = 0; i < 3; i++) {23             threadPool.execute(new Runnable() {24 25                 @Override26                 public void run() {27 //                    调用方法28                     System.out.println("main方法中输出:" + get());29 30                 }31             });32         }33 34     }35     static Map
map = new HashMap
();36 public static String get() {37 // 创建读写锁38 ReadWriteLock rwl = new ReentrantReadWriteLock();39 String name;40 // 设置读锁41 rwl.readLock().lock();42 try {43 //每次获得都是为null!!!!44 name = map.get("id");45 System.out.println("重新进入方法集合的长度为:" + map.size());46 try {47 Thread.sleep(200);48 } catch (InterruptedException e) {49 // TODO Auto-generated catch block50 e.printStackTrace();51 }52 if (name == null) {53 // 如果name为null就释放读锁54 rwl.readLock().unlock();55 // 设置写锁,进行赋值56 rwl.writeLock().lock();57 try {58 //每个线程都会进来!!!!59 System.out.println(Thread.currentThread().getName() + "--jin--"60 + name);61 // 赋值并存入集合62 name = "zhangsan";63 map.put("id", name);64 System.out.println("在把数据存入集合后根据ID获得name: " + map.get("id"));65 } finally {66 rwl.readLock().lock();67 // 释放写锁68 rwl.writeLock().unlock();69 }70 }71 72 } finally {73 // 释放读锁74 rwl.readLock().unlock();75 }76 return name;77 }78 79 }

控制台输出:

重新进入方法集合的长度为:0

重新进入方法集合的长度为:0
重新进入方法集合的长度为:0
pool-1-thread-3--jin--null
在把数据存入集合后根据ID获得name: zhangsan
main方法中输出:zhangsan
pool-1-thread-2--jin--null
在把数据存入集合后根据ID获得name: zhangsan
main方法中输出:zhangsan
pool-1-thread-1--jin--null
在把数据存入集合后根据ID获得name: zhangsan
main方法中输出:zhangsan

在上面代码中有个问题没有解决,单纯的在读锁中读取和切换到写锁中写数据是没有问题的,但是我想在第一次写入之后存入集合避免以后进来都创建锁、写数据一系列动作,每次存到map的数据在再次访问的时候都没有了,本来我以为是线程太快排进去了,就在run方法中叫了sleep(),但是还是不行。

最后我在分配任务前也加了sleep(),居然就正常了,由此推断还是因为运行得太快全部都排进去了,但是不知道为什么在Run方法中调用方法前sleep()没有作用,或许是线程池分配任务机制有所不同

1 public static void main(String[] args) { 2         // TODO Auto-generated method stub 3         //创建线程池 4         ExecutorService threadPool = Executors.newFixedThreadPool(3); 5         for (int i = 0; i < 3; i++) { 6             try { 7                 Thread.sleep(2000); 8             } catch (InterruptedException e) { 9                 // TODO Auto-generated catch block10                 e.printStackTrace();11             }12             threadPool.execute(new Runnable() {13 14                 @Override15                 public void run() {16 //                    调用方法17                     System.out.println("main方法中输出:" + get());18 19                 }20             });21         }22 23 24     }25     static Map
map = new HashMap
();26 public static String get() {27 // 创建读写锁28 ReadWriteLock rwl = new ReentrantReadWriteLock();29 String name;30 // 设置读锁31 32 rwl.readLock().lock();33 try {34 35 name = map.get("id");36 System.out.println("重新进入方法集合的长度为:" + map.size());37 try {38 Thread.sleep(200);39 } catch (InterruptedException e) {40 // TODO Auto-generated catch block41 e.printStackTrace();42 }43 if (name == null) {44 // 如果name为null就释放读锁45 rwl.readLock().unlock();46 // 设置写锁,进行赋值47 rwl.writeLock().lock();48 try {49 System.out.println(Thread.currentThread().getName() + "--jin--"50 + name);51 // 赋值并存入集合52 name = "zhangsan";53 map.put("id", name);54 System.out.println("在把数据存入集合后根据ID获得name: " + map.get("id"));55 } finally {56 rwl.readLock().lock();57 // 释放写锁58 rwl.writeLock().unlock();59 }60 }61 62 } finally {63 // 释放读锁64 rwl.readLock().unlock();65 }66 return name;67 }

控制台输出:

重新进入方法集合的长度为:0

pool-1-thread-1--jin--null
在把数据存入集合后根据ID获得name: zhangsan
main方法中输出:zhangsan
重新进入方法集合的长度为:1
main方法中输出:zhangsan
重新进入方法集合的长度为:1
main方法中输出:zhangsan

 

转载于:https://www.cnblogs.com/wan-to-fly/archive/2013/03/04/2943497.html

你可能感兴趣的文章
如何把Json格式字符写进text文件中
查看>>
免费馅饼(动态规划)
查看>>
Linux uname命令
查看>>
PHP正则表达式及实例
查看>>
iOS - Swift NSPoint 位置
查看>>
2018(2017)美图java服务端笔试(回忆录)
查看>>
C++语言基础(10)-虚继承
查看>>
LINUX PID 1和SYSTEMD 专题
查看>>
linux CentOS6.5 yum安装mysql 5.6(转载&删改)
查看>>
Mongodb基础用法及查询操作[转载]
查看>>
马老师 生产环境mysql主从复制、架构优化方案
查看>>
ZXing工具类v1.0
查看>>
CXF Spring 实现WebService - 观千剑而后识器,操千曲而后晓声。 - 博客频道
查看>>
jquery--递增--年份的选择
查看>>
http://blog.csdn.net/huang_xw/article/details/7090173
查看>>
lua学习例子
查看>>
软件测试思想浅谈
查看>>
Linux入门基础 #8:Linux拓展权限
查看>>
Mac Pro 软件收藏
查看>>
斯内德将出任2020欧洲杯荷兰地区形象大使
查看>>