目录
1、前言
当前需求为:处理数据,将数据存储到数据库中,在存储的过程中,会先查询该数据是否已经存储在数据库中,由于处理数据过大,需要采用线程池的方式进行同时处理。
2、问题
采用以上手段编写逻辑时,会存在线程安全问题:边查边插(数据库查询数据不一致问题),导致数据的重复插入。因此需要采用手段约束数据重复的问题。
3、解决方法
3.1、方法一:数据库约束
给数据库中某个字段设计为唯一索引,即使在查询的时候没有查到相应的数据记录(实际已经存在数据库中),在插入的时候会报错字段重复的错误异常,导致数据记录插入失败,从而达到去重的问题。
3.2、方法二:使用锁进行线程的约束
根据实际业务场景选择合适的锁策略。乐观锁适用于写入冲突较少的场景,悲观锁适用于写入冲突较多的场景。
线程同步:使用同步机制,如ReentrantLock
、synchronized
等,确保同一时间只有一个线程能进行查询和插入操作。下面就使用线程同步机制,代码展示设计:
mybatis接口代码:
import org.apache.ibatis.annotations.*;
public interface UserMapper {
@Select("SELECT COUNT(*) FROM user WHERE username = #{username}")
int countByUsername(@Param("username") String username);
@Insert("INSERT INTO user (username, password, email) VALUES (#{username}, #{password}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insertUser(User user);
}
创建服务类代码:
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class UserService {
private final ExecutorService executorService;
private final SqlSessionFactory sqlSessionFactory;
public UserService(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
// 创建固定大小的线程池
this.executorService = Executors.newFixedThreadPool(10);
}
public void addUser(User user) {
executorService.submit(() -> {
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper userMapper = session.getMapper(UserMapper.class);
synchronized (UserService.class) {
// 在同步块内执行查询和插入操作
if (userMapper.countByUsername(user.getUsername()) == 0) {
userMapper.insertUser(user);
session.commit(); // 提交事务
}
}
}
});
}
}
以上只是一个小案例,实际使用场景要按照你的需求来。解释下以上代码:使用了UserService.class
作为锁对象,以确保同一时间只有一个线程能够执行查询和插入操作。这样可以避免并发问题,但可能会导致性能瓶颈,特别是在高并发场景下。可以考虑使用更细粒度的锁或者数据库级别的锁(如悲观锁)来优化性能。
4、总结
根据需求设计线程池操作数据库的逻辑,但是整个过程存在线程安全问题,因此,简单介绍了两个解决方式:①数据库表设置唯一索引字段 ②采用加锁的方式保证线程同步。使用时根据实际场景进行调整,过程写的比较宽泛,只介绍了两种方式,如果想要深入了解,还需进一步学习。当然,我希望可以通过我的小提示给困惑的你一个小小的答案。
学习之所以会想睡觉,是因为那是梦开始的地方。
ଘ(੭ˊᵕˋ)੭ (开心) ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)
------不写代码不会凸的小刘
文章评论