Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统
2023-09-14 09:00:18 时间
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的.
1.如何创建锁?
Lock lock = new ReentrantLock();
2.如何使用锁?
可以参看Lock文档,其使用格式如下:
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } }
在要用的方法前加上锁,比如写操作,然后在finally中将锁打开.
这里,将前文java核心知识点学习----多线程并发之线程同步中的代码改用Lock实现数据同步,改写代码如下:
package com.amos.concurrent; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @ClassName: LockTest * @Description: Lock学习 * @author: amosli * @email:hi_amos@outlook.com * @date Apr 22, 2014 1:48:36 AM */ public class LockTest { public static void main(String[] args) { new LockTest().init(); } private void init() { final OutPuter outPuter = new OutPuter(); // 新建一个线程 new Thread(new Runnable() { public void run() { while (true) { // 休息10ms try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } outPuter.output("hi_amos");// 输出 } } }).start(); new Thread(new Runnable() { public void run() { while (true) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } outPuter.output("amosli"); } } }).start(); } static class OutPuter { // 方式1:使用synchronized关键字 // public synchronized void output(String name) { // int length = name.length(); // for (int i = 0; i < length; i++) { // System.out.print(name.charAt(i)); // } // System.out.println(); // } // 方式2:使用Lock锁 Lock lock = new ReentrantLock(); public void output(String name) { lock.lock();// 加锁 int length = name.length(); // 输出name,逐个字节读取,并输出 try { for (int i = 0; i < length; i++) { System.out.print(name.charAt(i)); } System.out.println(); } finally { lock.unlock();// 解锁 } } } }
3.synchronized关键字与Lock的区别?
1).Lock是Java5中的新特性,更加面向对象.更类似于生活中的锁.
2).Lock锁一般需要手动开启和关闭,而synchronized则不需要.
建议优先使用Lock.
4.注意事项:
1)多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥.
2)要实现两个线程互斥,那么要将锁加到同一个被访问对象上.
3)如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁,总之,读的时候用读锁,写的时候用写锁!
5.设计一个缓存系统
什么是缓存系统? 就是看本地是否已经缓存过此数据,如果已经缓存过,那就直接拿来用;如果没有缓存过,那就查询数据库.
下面看代码:
private Map<String, Object> cache = new HashMap<String, Object>(); public synchronized Object getData(String key){ Object object = cache.get(key); if (object==null) { object = "1323";//实际是去queryDB(); } return object; }
这里其实是一个超级简单的缓存系统,原理就是:第一次访问的时候把值存入到cache中,第二次访问时,先去看cache中是否有值如果有值,那么就直接去取值,而不是从数据库中去取.
为什么要加上synchronized? 这是为了保持数据互斥,访问的时候不相互影响,因为其中有对object进行赋值操作,这是一个写操作,所以最好加上锁.
如何优化?
private ReadWriteLock rwl = new ReentrantReadWriteLock(); public synchronized Object getData(String key){ rwl.readLock();//read lock Object object = cache.get(key); try{ if (object==null) { rwl.readLock().unlock();//释放锁 rwl.writeLock().lock();//对写加锁 try{ object = "1323";//实际是去queryDB(); }finally{ rwl.writeLock().unlock(); } } }finally{ rwl.readLock().unlock(); } return object; }
上面的代码运用到了刚学到的知识,对所有读和写进行加锁,以保持线程间的互斥,要特别注意的是要在finally中把锁打开,不管程序是否执行成功,因为如果不解锁,那么程序将会产生死锁,关于死锁,将在接下来的文章中介绍.
相关文章
- java 怎样卸载一个类_Java 动态卸载类[通俗易懂]
- java四舍五入函数的用法
- java helloworld源代码_Java Hello World源代码notepad++版
- java判断一个对象是否为空_Java中判断对象是否为空的方法的详解
- java启动器_JAVA基础:Java 启动器如何查找类
- java用正则表达式大全_Java 正则表达式 大全「建议收藏」
- java清除浏览器缓存[通俗易懂]
- java 生成xml dom4j_Java生成xml——DOM4J生成
- java 随机数算法_Java随机数算法原理与实现方法实例详解
- java输出一个数组的元素_Java输出数组元素「建议收藏」
- 实现Java程序操作MySQL数据库(java调用mysql)
- Java 解析Excel(xls、xlsx两种格式)详解编程语言
- Java:执行jar文件命令详解编程语言
- Java与Oracle的完美结合(java和oracle)
- Java下使用Redis进行高效缓存优化(Redis缓存java)
- 版本配置Linux系统的默认Java版本(linux默认java)
- 策略解决Redis Java过期策略问题(redisjava过期)
- 互操作Java与Redis缓存互操作实践(redis缓存与java)
- 一部分Oracle驱动Java的成功之路(java是oracle的)
- Redis实现Java语言下的遍历处理(redis遍历java)
- java中数组listmap三者之间的互转介绍
- java中thread线程start和run的区别