使用HashMap或者List模拟数据库插入和查询数据

理解代码必备

  1. 参数中使用(String... keys)
    在 Java 中,String... keys 这种语法被称为可变参数(Varargs),是 Java 5 引入的特性,用于简化方法参数的定义。它允许方法接收任意数量(包括零个)的同一类型参数
    用此可变参数 可以省去创建String\[\]数组的功夫,而且不写和写几个都行,更加灵活
    可变参数使用限制:
    一个方法只能有一个可变参数
    可变参数必须是方法的最后一个参数
  2. 对于CountDownLatch的使用
    CountDownLatch 是 Java 并发包(java.util.concurrent)中的一个同步工具类,用于协调多个线程的执行顺序。它允许一个或多个线程等待其他线程完成操作后再继续执行,类似于一个 "倒计时门闩"
    会对其进行计数,用一次减一进行计数,这就是为什么要用try,finally
  3. threadPool.execute(Runnable task)
    threadPool.execute(Runnable task) 是 Java 线程池(ExecutorService)的核心方法之一,用于提交一个任务(Runnable 对象)到线程池执行。它是线程池管理多线程的基础操作,下面详细解释其功能和用法。

HashMap模拟数据库

bash 复制代码
package KaKe;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SimpleDatabase {
    private Map<String,String> dataStore;//HashMap模拟数据库存储数据
    private ExecutorService threadPool;//线程池管理查询线程
    //无参构造器
    public SimpleDatabase(){
        //给HashMap存储数据库创建对象
        dataStore  = new HashMap<>();
        //线程池中创建三个线程
        threadPool = Executors.newFixedThreadPool(3);
    }
    //模拟数据库插入
    public void insert(String key,String value){
        dataStore.put(key,value);
        System.out.println("key:"+key+",value:"+value);
    }
    //多线程查询
    public void queryWithThreads(String... keys){
        if(keys==null || keys.length==0){
            System.out.println("查询条件为空");
            return;
        }
        CountDownLatch latch = new CountDownLatch(keys.length);//给keys数组中的每个key计数
        System.out.println("启动多线程查询");
        for (String key : keys) {
            //提交任务到线程池中执行
            threadPool.execute(()->{
                try{
                    //模拟查询操作
                    String value = dataStore.get(key);
                    String result = value != null ?
                            "线程["+Thread.currentThread().getName()+"]查询到:key="+key+",value="+value:
                            "线程["+Thread.currentThread().getName()+"]查询不到:key="+key;
                    System.out.println(result);
                }finally {
                    latch.countDown();//执行完毕,计数减一
                }
            });
        }
        try{
            latch.await();//等待所有线程执行完毕
            System.out.println("所有查询线程执行完成");
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void shutdown(){
        if (threadPool!=null && !threadPool.isShutdown()){
            threadPool.shutdown();
            System.out.println("数据库连接关闭");
        }
    }

    public static void main(String[] args) {
        SimpleDatabase db = new SimpleDatabase();
        //插入数据
        db.insert("user1","张三");
        db.insert("user2","李四");
        db.insert("user3","王五");
        db.queryWithThreads("user1","user2","user3");
        db.shutdown();
    }

}
bash 复制代码
key:user1,value:张三
key:user2,value:李四
key:user3,value:王五
启动多线程查询
线程[pool-1-thread-3]查询到:key=user3,value=王五
线程[pool-1-thread-2]查询到:key=user2,value=李四
线程[pool-1-thread-1]查询到:key=user1,value=张三
所有查询线程执行完成
数据库连接关闭

List模拟数据库

bash 复制代码
package KaKe;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ListBasedDatabase {
    private List<Map.Entry<String,String>> dataStore;
    private ExecutorService threadPool;
    public ListBasedDatabase(){
        //使用线程安全的ArrayList保证线程安全
        dataStore = new CopyOnWriteArrayList<>();
        threadPool = Executors.newFixedThreadPool(3);
    }
    public void insert(String key,String value){
        for (Map.Entry<String, String> entry : dataStore) {
            if (entry.getKey().equals(key)){
                System.out.println("插入失败:key="+key+"已存在");
                return;
            }
        }
            dataStore.add(Map.entry(key, value));
            System.out.println("插入成功:key="+key+"value="+value);
    }
    public void queryWithThreads(String... keys){
        if (keys==null || keys.length==0){
            System.out.println("查询条件为空");
            return;
        }
        CountDownLatch latch = new CountDownLatch(keys.length);
        System.out.println("启动线程查询:");
        for (String key : keys) {
            threadPool.execute(()->{
                try{
                    String result = searchInList(key);
                    System.out.println("线程["+Thread.currentThread().getName()+"]:"+result);
                }finally {
                    latch.countDown();
                }
            });
        }
        try{
            latch.await();
            System.out.println("所有线程查询执行完成");
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
    //在List中查找数据
    private String searchInList(String key){
        for (Map.Entry<String,String> entry: dataStore){
            if (entry.getKey().equals(key)){
                return "查询到数据:key="+key+",value="+entry.getValue();
            }
        }
        return "未找到key="+key+"的数据";
    }
    public void shutdown(){
        if (threadPool!=null && !threadPool.isShutdown() ){
            threadPool.shutdown();
            System.out.println("数据库关闭连接");
        }
    }

    public static void main(String[] args) {
        ListBasedDatabase db = new ListBasedDatabase();
        // 插入数据
        db.insert("user1", "张三");
        db.insert("user2", "李四");
        db.insert("user3", "王五");
        db.insert("user4", "赵六");
        db.insert("user5", "董七");
        db.queryWithThreads("user1","user2","user3","user4","user5");
        db.shutdown();
    }
}
bash 复制代码
插入成功:key=user1value=张三
插入成功:key=user2value=李四
插入成功:key=user3value=王五
插入成功:key=user4value=赵六
插入成功:key=user5value=董七
启动线程查询:
线程[pool-1-thread-1]:查询到数据:key=user1,value=张三
线程[pool-1-thread-3]:查询到数据:key=user3,value=王五
线程[pool-1-thread-1]:查询到数据:key=user4,value=赵六
线程[pool-1-thread-2]:查询到数据:key=user2,value=李四
线程[pool-1-thread-3]:查询到数据:key=user5,value=董七
所有线程查询执行完成
数据库关闭连接

总结:

其实本质上还是使用HashMap ,只不过后者是用List将其HashMap封装起来,然后插入和查询

相关推荐
大圣编蚕几秒前
Redis 为什么快?现在还是单线程吗?
数据库·redis·缓存
鸥梨菌Honevid11 分钟前
UVM 面试高频:uvm_test_top 与 uvm_config_db 路径机制全解析
数据库·面试·职场和发展
极小狐16 分钟前
MR 里测试摘要空白、覆盖率不显示?JUnit 与覆盖率配置 9 步排查
数据库·ci/cd·junit·单元测试·mr·devops·代码覆盖率
silvamux_18 分钟前
MiniMax API 调用教程:兼容 OpenAI 写法
java·数据库·elasticsearch
zh731421 分钟前
sqlforge一个SQL 格式化与方言转换工具
数据库·sql
染指111022 分钟前
145.Agent-LangGraph基础概念和安装和简单代码示例
java·服务器·数据库·langchain·agents
太理摆烂哥36 分钟前
MySQL表的操作
数据库
lbb 小魔仙38 分钟前
时序数据库是什么?2026 年五款工业时序数据库横评与场景解析
数据库·时序数据库
零基础12342 分钟前
权限管理怎么做?从“资格”与“空间”双维度设计一套可落地的权限体系
java·服务器·数据库
小小龙学IT1 小时前
PostgreSQL 服务端机制与 SQL 实战深度解析:从 MVCC 到查询优化器
数据库·sql·postgresql