Java线程池为什么执行效率没有显示创建线程高呢

问题描述

同步二十万条数据,我想使用多线程同时进行, 但为什么我使用线程池同步数据的效率比我显示创建线程更慢呢?

这是显示创建线程:

    for (int i = 0; i < studentIdList.size(); i++) {
      List<String> studentIds = studentIdList.get(i);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (String per : studentIds) {
                      //数据库操作
                }
            }
        }, "线程" + i);
        thread.start();
    }
        

//这是使用线程池创建

    ExecutorService exec= Executors.newCachedThreadPool();
    for (int i = 0; i < studentIdList.size(); i++) {
        List<String> studentIds = studentIdList.get(i);
        exec.execute(new Runnable() {
            @Override
            public void run() {
                for (String per : studentIds) {
                 //数据库操作
                }
            }
        });
        exec.shutdown();
    }

不应该是使用了线程池 效率更高更快吗,为什么反而显示创建线程保存到数据库更快呢

阅读 4.3k
2 个回答

首先你得保证你的测试代码是正确的。。。

很显然,线程池的代码有几个问题:

  1. exec 初始化的时候,线程池内部有多少线程?如果线程池内部线程本身比较少,循环时候,线程池也会通过 new Thread 线程的方式为线程池补充线程。
  2. 也是最重要的一点,for 循环中每次都 exec.shutdown(),调用该方法的意思是关闭当前线程池。线程池本身并不需要关闭。更不应该在 for 循环中关闭。
    /**
     * Initiates an orderly shutdown in which previously submitted
     * tasks are executed, but no new tasks will be accepted.
     * Invocation has no additional effect if already shut down.
     *
     * <p>This method does not wait for previously submitted tasks to
     * complete execution.  Use {@link #awaitTermination awaitTermination}
     * to do that.
     *
     * @throws SecurityException {@inheritDoc}
     */
    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(SHUTDOWN);
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }

查看 shutdown 源码,可以看到 shutdown 后,线程池不再接受新任务。
也就是第一次 for 循环,线程池增加了一个任务。然后调用 shutdown 后,线程池就不再接受新的任务了。
意思是说:线程池的代码其实只有一个线程在处理任务,而上面的 new Thread 代码却有多个线程在处理。
当然是上面的代码处理的快。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题