Java 在循环中重新创建ExecutorService以进行批处理

Java 在循环中重新创建ExecutorService以进行批处理,java,multithreading,concurrency,executorservice,Java,Multithreading,Concurrency,Executorservice,示例:我需要处理数百万条记录,我想并行处理它们以加快处理速度。为此,我想在Executor服务中使用线程池。每项任务最多需要几秒钟。为了避免在一个线程池中为每条记录创建数百万个线程(在我的例子中,这会导致内存问题),我决定成批处理记录 我想为每个批使用一个新的线程池。我让Executor服务等待批处理任务完成,然后关闭Executor服务并创建一个新服务来处理下一批任务。 我是这样做的: /*...................*/ int count = 1; ExecutorService

示例:我需要处理数百万条记录,我想并行处理它们以加快处理速度。为此,我想在Executor服务中使用线程池。每项任务最多需要几秒钟。为了避免在一个线程池中为每条记录创建数百万个线程(在我的例子中,这会导致内存问题),我决定成批处理记录

我想为每个批使用一个新的线程池。我让Executor服务等待批处理任务完成,然后关闭Executor服务并创建一个新服务来处理下一批任务。 我是这样做的:

/*...................*/
int count = 1;
ExecutorService executor = buildExecutor(CORE_THREADS, MAX_THREADS);
            while (/* there is a record */) {
                executor.execute(new ProcessRecordThread(record));
                count++;
                if (count % BATCH_SIZE == 0) {
                    executor.shutdown();
                    executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
                    executor = buildExecutor(CORE_THREADS, MAX_THREADS);
                }
            }
 /*................*/
方法创建执行器服务

private static ExecutorService buildExecutor(int corePoolSize, int maximumPoolSize) {
            return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 0L,
                    TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue(),
                    Executors.defaultThreadFactory());
        }
我知道创建线程池会给处理增加一些开销。在循环中创建executor服务被认为是不好的做法。我应该注意哪些权衡


有没有办法通过使用一个线程池来实现这种行为?

构建类有一个静态公共数据源,如单例模式中的
C3P0
(开源)来管理连接

配置
c3p0.maxPoolSize=x
并运行x个线程从数据源获取连接,然后执行sql

例子:
公共类C3P0Pool{
私有静态ComboPooledDataSource CPDS=新ComboPooledDataSource(“c3p0”);
公共静态连接getConnection()引发SQLException{
返回CPDS.getConnection();
}
公共静态数据源getDataSource(){
return CPDS;//QueryRunner可以用DataSource构造
}
}

您不必关闭数据源,连接将在执行
connection时返回到数据源。close()

构建类在单例模式下有一个静态公共数据源,如
C3P0
(开源)来管理连接

配置
c3p0.maxPoolSize=x
并运行x个线程从数据源获取连接,然后执行sql

例子:
公共类C3P0Pool{
私有静态ComboPooledDataSource CPDS=新ComboPooledDataSource(“c3p0”);
公共静态连接getConnection()引发SQLException{
返回CPDS.getConnection();
}
公共静态数据源getDataSource(){
return CPDS;//QueryRunner可以用DataSource构造
}
}

您不必关闭数据源,在执行
connection.close()

时,连接将返回到数据源。在这里重新创建执行器有什么意义?为什么不使用同一个线程呢?否则,它会在一个线程池中创建数百万个线程,并导致内存堆问题。至少对于基本的JVM设置,在这里重新创建执行器有什么意义?为什么不使用同一个线程呢?否则,它会在一个线程池中创建数百万个线程,并导致内存堆问题。至少对于基本的JVM设置,我没有连接到数据库或运行任何sql。一百万条记录可能是来自fileoops…sry的行。那么,为什么要在这里重新创建ThredPool呢?请尝试Es=Executors.newFixedThreadPool(num)并设置allowCoreThreadTimeOut=true。线程将在其作业完成时返回ThreadPool。您只需执行Es.execute(Runnable命令)有一个想法是在SpringBoot中使用ThreadPoolTaskExecutor,但我现在还没有完全意识到,你可以尝试一下。我认为你应该每秒检测工作队列(如LinkedBlockingQueue),并按计划执行任务,以避免阻塞工作队列。我没有连接到数据库或运行任何sql。一百万条记录可能是来自fileoops…sry的行。那么,为什么要在这里重新创建ThredPool呢?请尝试Es=Executors.newFixedThreadPool(num)并设置allowCoreThreadTimeOut=true。线程将在其作业完成时返回ThreadPool。您只需执行Es.execute(Runnable命令)有一个想法是在SpringBoot中使用ThreadPoolTaskExecutor,但我现在还没有完全意识到,您可以尝试一下。我认为您应该每秒检测工作队列(如LinkedBlockingQueue),并按计划执行任务,以避免阻塞工作队列