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