Java Spring批处理-如何使用ThreadPoolTaskExecutor动态增加和减少线程

Java Spring批处理-如何使用ThreadPoolTaskExecutor动态增加和减少线程,java,concurrency,spring-batch,Java,Concurrency,Spring Batch,我对SpringBatch还比较陌生,所以这可能是我对SpringBatch缺乏了解。我想了解在我的作业运行时,如何结合使用ThreadPoolTaskExecutor和ThreadPoolExecutor动态增加和减少线程。我已经尝试将ThreadPoolTaskExecutor和ThreadPoolExecutor都分为子类,这样我就可以访问beforeExecute()和afterExecute(),如果corepoolsize使用此站点上列出的方法减小,则可以终止线程 我似乎不理解的是,

我对SpringBatch还比较陌生,所以这可能是我对SpringBatch缺乏了解。我想了解在我的作业运行时,如何结合使用ThreadPoolTaskExecutor和ThreadPoolExecutor动态增加和减少线程。我已经尝试将ThreadPoolTaskExecutor和ThreadPoolExecutor都分为子类,这样我就可以访问beforeExecute()和afterExecute(),如果corepoolsize使用此站点上列出的方法减小,则可以终止线程

我似乎不理解的是,当我重写返回ExecutorService的initializeExecutor()方法时,它显然没有在父类(ThreadPoolTaskExecutor)中设置(私有内部)threadPoolExecutor变量。设置私有执行器服务执行器;(来自ExecutorConfigurationSupport类)

由于threadPoolExecutor不是受保护的成员,因此我无法访问它。如果没有设置,当我运行时,当我检查封面下的错误时,显然会在Spring框架中得到一个“ThreadPoolExecutor not initialized”错误

公共类MyThreadPoolTaskExecutor扩展了ThreadPoolTaskExecutor {

@覆盖
受保护的执行器服务初始化执行器(ThreadFactory tf,RejectedExecutionHandler reh)
{
BlockingQueue=createQueue(整数.MAX_值);
MyThreadPoolExecutor tp_executor=新的MyThreadPoolExecutor(this.getCorePoolSize()、this.getMaxPoolSize()、this.getKeepAliveSeconds()、TimeUnit.SECONDS、queue);
//如果查看父类(ThreadPoolTaskExecutor),它接下来将执行此调用。
//this.threadPoolExecutor=执行器;
//这是一个私有成员,无法通过任何方法进行设置。
返回tp_执行器;
}
}

公共类MyThreadPoolExecutor扩展了ThreadPoolExecutor {

public MyThreadPoolExecutor(int-corePoolSize、int-maxPoolSize、long-keepAliveTimeout、TimeUnit-TimeUnit、BlockingQueue-workQueue、ThreadFactory-tf、RejectedExecutionHandler-reh)
{
super(corePoolSize、maxPoolSize、keepAliveTimeout、timeunit、workQueue、tf、reh);
}
执行前受保护的void(最终线程、最终可运行作业)
{   
...
}
}


有人能解释一下我的方法中缺少了什么吗?

我假设您希望在一个作业步骤中使用一个线程数,在另一个作业步骤中使用另一个线程数。实现这一点的简单方法是声明两个具有必要线程数的独立执行器,零
corePoolSize
(不需要时不创建线程)和零
keepAliveSeconds
(不再需要时不保留线程)。然后在一个步骤中注入第一个执行器,在另一个步骤中注入第二个执行器

@Configuration
public class Conf {

    @Bean
    public TaskExecutor executorA(@Value("${first.number.of.threads}") int numberOfThreads) {
        return executor(numberOfThreads);
    }

    @Bean
    public TaskExecutor executorB(@Value("${second.number.of.threads}") int numberOfThreads) {
        return executor(numberOfThreads);
    }

    private TaskExecutor executor(int numberOfThreads) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(0);
        executor.setMaxPoolSize(numberOfThreads);
        executor.setAllowCoreThreadTimeOut(true);
        executor.setKeepAliveSeconds(0);
        return executor;
    }
}

为什么要尝试动态更改正在运行的线程数量?我们的生产机器上运行着大量的作业。如果容量在一段时间内释放在一个盒子上,我们的prod支持人员可能希望在一段时间内为一个作业抛出更多线程。在一段时间内动态增加和/或减少线程的能力是一个非常有用的工具,可以在一个盒子上有很多活动的情况下提供产品支持。这听起来像是一个动态资源管理的解决方案。您是如何确定是否有更多的资源可用,或者您是否正在尝试动态更改线程数量?我们的产品支持团队利用工具,如果可用的cpu可用,他们会希望动态增加此作业的线程数量,以实现最大吞吐量。不完全是这样。我可能有一个步骤需要处理几十万条记录,因此即使任务执行得相当快,也可能需要相当长的时间才能完成。由于我们的机器上运行着大量的作业,因此可能存在活动较少的时间窗口,因此我们希望在一段时间内增加线程的数量(同一步骤)。我想为生产支持提供一个动态调优功能,这样他们就可以在给定的步骤中增加和/或减少线程。我相信这已经由ThreadPoolExecutor管理了。我正在查看一些文档,并将尝试返回you@EdT似乎可以定义最大池大小以满足高活动需求,定义核心池大小以满足最低活动需求(可以是0)然后设置非零keep alive seconds,以允许在没有活动时自动将线程关闭回核心池大小。增加线程可以正常工作,并动态添加线程,但减少核心池大小不会自动关闭线程。看来,你必须亲自具体执行这项任务。试图获得执行该任务的实际钩子是引发我的问题的原因,也是我共享上述代码的原因。我说的是指定corePoolSize=5、maxPoolSize=10和keepAliveSeconds=7。默认情况下,池将有5个线程。如果有足够的任务,它的大小将增加到10个线程。线程6-10将在7秒不活动后自动停止,因此当没有足够的任务时,池将恢复到大小5。
public MyThreadPoolExecutor(int corePoolSize, int maxPoolSize, long keepAliveTimeout, TimeUnit timeunit, BlockingQueue<Runnable> workQueue, ThreadFactory tf, RejectedExecutionHandler reh) 
{
    super(corePoolSize, maxPoolSize, keepAliveTimeout, timeunit, workQueue, tf, reh);
}

protected void beforeExecute (final Thread thread, final Runnable job) 
{   
  ...
}
@Configuration
public class Conf {

    @Bean
    public TaskExecutor executorA(@Value("${first.number.of.threads}") int numberOfThreads) {
        return executor(numberOfThreads);
    }

    @Bean
    public TaskExecutor executorB(@Value("${second.number.of.threads}") int numberOfThreads) {
        return executor(numberOfThreads);
    }

    private TaskExecutor executor(int numberOfThreads) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(0);
        executor.setMaxPoolSize(numberOfThreads);
        executor.setAllowCoreThreadTimeOut(true);
        executor.setKeepAliveSeconds(0);
        return executor;
    }
}