解决线程池执行数据库操作,同时插入相同的数据

222 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第九天,点击查看活动详情


目前的需求是,使用定时任务加线程池执行数据库操作时,会同时插入相同的数据,希望线程池执行时,不同的id可以同时执行查询并插入数据库,相同的id等第一个id执行完成再执行下一个。

 @Test
    public void contextLoads() {
        //进行异步任务列表
        List<FutureTask<Integer>> futureTasks = new ArrayList<FutureTask<Integer>>();
        //线程池 初始化十个线程 实现重用
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        long start = System.currentTimeMillis();
 
        //测试多个id同时进入线程池,并执行操作,模拟多个相同的数据与不同的数据
        List<String> list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("a");
        list.add("c");
        list.add("a");
        list.add("b");
        for (int j = 0; j < 10; j++) {
            for (int i = 0; i < list.size(); i++) {
                final int t = i;
                //创建一个异步任务
                FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
                    @Override
                    public Integer call() throws Exception {
                        b(list.get(t));
                        return 1;
                    }
                });
                futureTasks.add(futureTask);
                executorService.submit(futureTask);
            }
            int count = 0;
            for (FutureTask<Integer> futureTask : futureTasks) {
                //futureTask.get() 得到我们想要的结果
                //该方法有一个重载get(long timeout, TimeUnit unit) 第一个参数为最大等待时间,第二个为时间的单位
                try {
                    //执行完成后,记录所有执行的结果
                    count += futureTask.get(600, TimeUnit.SECONDS);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            System.out.println("线程池" + j + "的任务全部完成:结果为:" + count);
        }
        //执行完成关闭线程池
        executorService.shutdown();
        long end = System.currentTimeMillis();
        //记录线程池所耗费的时间
        System.out.println("使用时间:" + (end - start) + "ms");
 
    }
 
    public void b(String a) {
        //如果a参数是new出来的,则用a.intern()
        synchronized (a) {
            System.out.println(a + " " + Thread.currentThread().getName() + " 进入处理--");
            try {
                //休眠一段时间,模拟业务逻辑操作
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(a + " " + Thread.currentThread().getName() + " 处理结束---");
        }
    }

运行出来的结果如下:

image.png

可以看到,已经实现了之前的需求,不同的id可以同时执行查询并插入数据库,相同的id等第一个id执行完成再执行下一个