【juc】ReentrantReadWriteLock之缓存(仅当学习)

目录

一、说明

  • 1.针对于读多写少的情况
  • 2.先查缓存,没有再去查库

二、代码示例

2.1 pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.learning</groupId>
    <artifactId>jdbc</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.26</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.16</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
    </dependencies>
</project>
2.2 示例代码
package com.learning;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.cache.CacheKey;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class DataCache {
    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    private Map<CacheKey, Object> map = new HashMap<>();

    private static DruidDataSource druidDataSource = new DruidDataSource();
    private static JdbcTemplate jdbcTemplate;
    static {
        druidDataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");
        jdbcTemplate = new JdbcTemplate(druidDataSource);
    }

    public <T> T queryOne(Class<T> beanClass, String sql, Object... args){
        // 从缓存中查找,找到则直接返回
        CacheKey key = new CacheKey(new Object[]{sql, args});
        reentrantReadWriteLock.readLock().lock();
        try{
            T value = (T)map.get(key);
            if(value != null){
                return value;
            }
        }finally{
            reentrantReadWriteLock.readLock().unlock();
        }
        reentrantReadWriteLock.writeLock().lock();
        try{
            // 多个线程,再获取一遍,检查一下,是否有线程写入成功了
            T value = (T) map.get(key);
            if(value == null){
                // 缓存中没有,查询数据库
                value = queryDatabase(beanClass, sql, args);
                map.put(key, value);
            }
            return value;
        }finally {
            reentrantReadWriteLock.writeLock().unlock();
        }
    }

    private <T> T queryDatabase(Class<T> beanClass, String sql, Object[] args) {
        BeanPropertyRowMapper beanPropertyRowMapper = new BeanPropertyRowMapper<T>();
        beanPropertyRowMapper.setMappedClass(beanClass);
        System.out.println("sql:"+sql);
        List<T> list = jdbcTemplate.query(sql, args, beanPropertyRowMapper);
        return list.get(0);
    }

    public static void main(String[] args) {
        DataCache dataCache = new DataCache();
        String sql = "select * from student where id = ?";
        Object[] param = new Object[]{1};
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                Student student = dataCache.queryOne(Student.class, sql, param);
                System.out.println(student);;
            }).start();
        }
    }
}
2.3 实体类
package com.learning;

import lombok.Data;

@Data
public class Student {
    private String id;
    private String name;
    private int age;
}

三、示例截图

相关推荐
唐僧洗头爱飘柔95271 个月前
(Java并发编程——JUC)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
java·设计模式·并发编程·juc·reentrantlock·顺序控制·生产者与消费者
慕木沐1 个月前
【JUC并发】cmpxchg和lock指令
后端·并发·juc·汇编指令
HelloWorld. py3 个月前
JUC-ReentrantLock 锁粒度为什么更小
java·juc
lazy★boy3 个月前
JUC学习笔记(一)
juc
lazy★boy3 个月前
JUC学习笔记(三)
juc
小小工匠4 个月前
J.U.C Review - 常见的通信工具类解析
juc·countdownlatch·exchanger·phaser·semaphore·cyclicbarrier
水w4 个月前
“线程池中线程异常后:销毁还是复用?”
java·开发语言·线程池·juc
Czi橙4 个月前
深刻理解JDK中线程池的使用
java·spring·jdk·多线程·并发编程·juc
luming-024 个月前
图文详解ThreadLocal:原理、结构与内存泄漏解析
java·开发语言·jvm·java-ee·juc
Dexu74 个月前
【Java 并发编程】(三) 从CPU缓存开始聊 volatile 底层原理
juc·java并发编程