线上线程池翻车总结

项目描述:定时任务扫描300万条数据库记录,并对每条记录执行检查操作(调用其他服务接口,发送短信等)。

版本迭代记录:

  1)第一版:一次查询全部300万条数据放在JVM内存中,没有使用线程池,使用固定20个线程,每个线程循环不停的从内存中取一条数据执行,直到所有数据全部执行完为止。

    这种方式耗时大约3个半小时,代码如下:

 // 实现runnable接口的线程,infos:全部300条任务
            CheckTask checkTask = new CheckTask(infos);
            // 固定20个线程执行,线程不能回收再利用(线程池可以)
            for (int i = 0; i < 20; i++) {
                Thread t = new Thread(checkTask, name + "_" + i);
                t.start();
            }

    private class CheckTask implements Runnable {
        private List<Info> infos;
        private volatile int count = 0;

        public CheckTask(List<Info> infos) {
            this.infos= infos;
        }

        @Override
        public void run() {
            boolean done = false;
            while (!done) {
                try {
                    Info info = null;
                    // 使用同步锁
                    synchronized (infos) {
                        if (count < infos.size()) {
                            info = infos.get(count);
                            count++;
                        } else {
                            done = true;
                            break;
                        }
                    }

                    if (info != null) {
                        // 对取到的一个任务执行业务逻辑
                        ...
                    }
                } catch (Exception e) {
                    // 异常处理
                }
            } // while
        }
    }

  2)第二版:使用线程池,线程池核心线程数为1,最大线程数为50,等待队列为100。每次执行1000条任务

  3)第三版:

猜你喜欢

转载自www.cnblogs.com/yangyongjie/p/12508820.html