多线程并发更新实时数据

概述

项目中遇到一个需要批量更新数据的需求,要求将实时传过来的数据实时更新到数据库中

问题

一开始只是简单的调用mapper的更新接口,没啥问题,后期发现数据太多一直在请求接口,数据无法实时更新到数据库中,后来引入了线程池解决了这个问题

线程池

线程池–基于池话思想的线程管理工具,用户无需关注如何创建、调度线程来执行任务,用户只需提供 Runnable、Thread对象,将任务的运行逻辑提交到run方法中,由线程池完成线程的调配和任务的执行部分,这样带来的好处是减少了线程线程创建、销毁的开销,避免了线程数量过多导致的内存占用问题,极大的提高了资源利用率、响应速度

七大参数:

  1. corePoolSize 核心线程数目

  2. maximumPoolSize 最大线程数目

  3. keepAliveTime 生存时间

  4. unit 时间单位

  5. workQueue 工作队列

  6. threadFactory 线程工厂

  7. handler 拒绝策略 - 当所有线程都在繁忙,workQueue 也放满时,会触发拒绝策略。

(1)抛异常 java.util.concurrent.ThreadPoolExecutor.AbortPolicy。

(2)由调用者执行任务 java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy。

(3)丢弃任务 java.util.concurrent.ThreadPoolExecutor.DiscardPolicy。

(4)丢弃最早排队任务 java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy

线程池的执行流程
多线程并发更新实时数据_第1张图片
1)、如果当前运行的线程少于 corePoolSize,则创建新线程来执行任务。
2)、如果运行的线程等于或大余 corePoolSize,则将任务加入 阻塞队列BlockingQueue中。
3)、如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任
4)、如果创建新线程将使当前运行的线程超过 maximumPoolSize,任务将被拒绝,并调用RejectedExecutionHandler.rejectedExecutor() 方法。

demo

类图
多线程并发更新实时数据_第2张图片

线程类:需要外界提供service和相应的数据map

public class CameraThreadHandler extends Thread{

    private NewLocatorService newLocatorService;

    private Map<String, List<Map<String,Integer>>> map;

    public CameraThreadHandler(NewLocatorService newLocatorService,Map<String, List<Map<String,Integer>>> map){

        this.newLocatorService = newLocatorService;
        this.map = map;

    }

    @Override
    public void run() {
        newLocatorService.storeCameraInfo(map);
    }
}

线程关联类,暂且这样称呼,为线程提供初始化数据

 @Autowired
    private NewLocatorService newLocatorService;

    private ExecutorService executorService =
            new ThreadPoolExecutor(5, 10, 1000, TimeUnit.MILLISECONDS,
                    new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.DiscardOldestPolicy());


    @ServiceActivator(inputChannel = "udpHandle1")
    public void udpMessageHandle(String message) throws Exception {

        try {
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, List<Map<String,Integer>>> map = new HashMap<>();
            executorService.execute(new CameraThreadHandler(newLocatorService,objectMapper.readValue(message, map.getClass())));
            log.info("message:" + message);
        }catch (Exception e){
            e.printStackTrace();
            //return R.error();
        }

    }

补充一点,数据初始化,可直接注入后传值,

多线程并发更新实时数据_第3张图片
也可以用
多线程并发更新实时数据_第4张图片
SpringContextUtil:

@Slf4j
@Configuration
public class SpringContextUtil implements ApplicationContextAware {


    // Spring应用上下文环境
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static <T> T getBean(String beanId) {
        T bean = null;
        try {
            if (StringUtils.isNotEmpty(StringUtils.trim(beanId))) {
                bean = (T) applicationContext.getBean(beanId);
            }
        } catch (NoSuchBeanDefinitionException e) {
            log.error("获取bean失败");
            return null;
        }
        return bean;
    }

    public static <T> T getBean(String... partName) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < partName.length; ++i) {
            sb.append(partName[i]);
            if (i != partName.length - 1) {
                sb.append(".");
            }
        }
        return getBean(sb.toString());
    }


}

你可能感兴趣的:(多线程,java,架构,开发语言)