#循环查询数据后使用线程去更新数据,如果更新速度慢,那么更新第一次数据时,线程中传入的可能是第3次或第4次查询出的数据吗
代码如下
package com.test.thread.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.test.thread.mapper.UserMapper;
import com.test.thread.pojo.User;
import com.test.thread.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @author清梦
* @site www.xiaomage.com
* @company xxx公司
* @create 2023-10-13 22:25
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
@Qualifier("taskExecutor")
private TaskExecutor taskExecutor;
@Override
public void batchUpdate(){
for (int i=0;i<20;i++){
List<User> list = new ArrayList<>();
Page<User> userPage = userMapper.selectPage(new Page<>(i, 500), null);
List<User> users = userPage.getRecords();
users.stream().forEach(user -> {
user.setName("test1");
list.add(user);
});
log.info("list:{}",list.toString());
int finalI = i;
taskExecutor.execute(new Runnable() {
@Override
public void run() {
try {
//Thread.sleep(1000);
}catch (Exception e){
log.error("线程失败:{}",e);
}
long start = System.currentTimeMillis();
log.info("开始更新,下标:{},大小:{}", finalI,list.size());
updateBatchById(list);
log.info("更新结束,下标:{},大小:{},耗时:{}", finalI,list.size(),System.currentTimeMillis()-start);
}
});
}
}
}
实体类
@TableName("tb_user")
@Data
public class User {
@TableId(type = IdType.AUTO)
private int id;
private String name;
}
线程池配置
@Configuration
public class MybatisConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
@Mapper
@Repository
public interface UserMapper extends BaseMapper<User> {
}
问题:
1.实现类中的代码有漏洞吗?
问题原因:本人在对oracle数据库进行更新时,业务逻辑如上,但是发布生产环境没有更新数据,组长看了代码后说是这种写法有漏洞。线程执行慢,list每次循环会被重新生成。重新写了一个类后传入list,再去执行线程,这样就更新了。但是本地测试并没有问题没搞不懂为啥。
2.线程中使用Thread.sleep(3000);后,线程后面的步骤就不走了,线程中断了,这是为什么?
3.在线程中添加了循环,添加耗时,结果也没有循环10000次,更新操作也没有执行,这是为什么呢?
taskExecutor.execute(new Runnable() {
@Override
public void run() {
try {
for (int j=0;j<10000;j++){
log.info("线程----第{}次查询",j);
userMapper.selectList(null);
log.info("线程----第{}次查询结束",j);
}
/*log.info("沉睡3秒");
long time = System.currentTimeMillis();
Thread.sleep(3000);
log.info("沉睡3秒结束,沉睡时间:{}",System.currentTimeMillis()-time);*/
}catch (Exception e){
log.error("线程失败:{}",e);
}
long start = System.currentTimeMillis();
log.info("开始更新,下标:{},大小:{}", finalI,list.size());
log.info("list:{}",list.toString());
updateBatchById(list);
log.info("更新结束,下标:{},大小:{},耗时:{}", finalI,list.size(),System.currentTimeMillis()-start);
}
});
4.代码循环时,到最后一次会出现线程中断异常,比如30万数据,更新到第60次后,走到线程中,进行更新时就会报错,提示线程中断。搞不懂为啥。