【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;
}

三、示例截图

相关推荐
lazy★boy19 天前
JUC学习笔记(一)
juc
lazy★boy20 天前
JUC学习笔记(三)
juc
小小工匠1 个月前
J.U.C Review - 常见的通信工具类解析
juc·countdownlatch·exchanger·phaser·semaphore·cyclicbarrier
水w1 个月前
“线程池中线程异常后:销毁还是复用?”
java·开发语言·线程池·juc
Czi橙1 个月前
深刻理解JDK中线程池的使用
java·spring·jdk·多线程·并发编程·juc
luming-022 个月前
图文详解ThreadLocal:原理、结构与内存泄漏解析
java·开发语言·jvm·java-ee·juc
Dexu72 个月前
【Java 并发编程】(三) 从CPU缓存开始聊 volatile 底层原理
juc·java并发编程
少不入川。2 个月前
ThreadLocal源码分析
java·juc·threadlocal
p_fly3 个月前
【JavaEE】CAS原理实现 + 常见应用
java·多线程·juc
喵先森爱吃鱼3 个月前
(五)共享模型之无锁
java·多线程·juc