java使用多线程提升效率

  • 应用场景
  • 代码实现
  • 运行结果


应用场景

循环处理一个列表,每个元素会进行一系列耗时读写操作。使用多线程提升运行速度

List list;
        for (Object obj : list) {
            long time = System.currentTimeMillis();
            obj.doingSomething();
            System.out.println(System.currentTimeMillis() - time);
        }

代码实现

创建一个线程池

private static final int CORE_POOL_SIZE = 10;
    private static final int MAX_POOL_SIZE = 10;
    private static final int QUEUE_CAPACITY = 100;
    private static final long KEEP_ALIVE_TIME = 1L;


ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),new ThreadPoolExecutor.CallerRunsPolicy());

将任务均分成数份,分成多少份取决于单个任务的执行时间以及cpu的能力。

//每个线程至少同步30条记录,计算线程数,不超过10个线程
        int threadSize = Math.min((int) Math.ceil(list.size() / 30D), MAX_POOL_SIZE);
        //计算平均每个任务数
        int taskNum = (int) Math.ceil(list.size() / (float) threadSize);
        for (int i = 0, size = threadSize - 1; i <= size; i++) {
            List<Object> subList= list.subList(i * taskNum, i < size ? (i + 1) * taskNum : list.size());
            ...
        }

使用Future保存每个线程执行结果,在最后轮询每个future状态来同步。

List<Future> taskList = new ArrayList<>();
		for (int i = 0, size = threadSize - 1; i <= size; i++) {
            List<Object> subList= list.subList(i * taskNum, i < size ? (i + 1) * taskNum : list.size());
            taskList.add(executor.submit(() -> {
                for (Object obj : list) {
            		long time = System.currentTimeMillis();
            		obj.doingSomething();
            		System.out.println(System.currentTimeMillis() - time);
        		}
            }));
        }
        for (Future f : taskList) {
            while (true) {
                if (f.isDone() && !f.isCancelled()) {
                    break;
                }
            }
        }

运行结果

测试运行1700条记录,每条记录耗时约200ms。
串行共耗时约460s,并行共耗时约60s。效率明显提升