Spring Java @Scheduling配置

问题描述 投票:0回答:2

使用@Scheduling在@Scheduled(fixedRate = 10000)运行方法并通过实现SchedulingConfigurer设置@Scheduling线程

    @Bean(destroyMethod="shutdown")
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(10);
    }

如果我使用Thread.sleep或Lock,除非Thread.sleep唤醒或锁定被清除,否则Executor不会创建其他线程。

有人可以解释内部工作,如果我有10个池大小,他们应该以10000毫秒的速度创建10个线程。

java spring multithreading spring-java-config spring-scheduled
2个回答
0
投票

基本上这种行为来自ScheduledExecutorService实现,它在春天内部使用。如果您将运行此代码,您将注意到相同的行为:

public static void main(String[] args) throws Exception {
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
    executor.schedule(() -> {
        System.out.println("Running task in thread " + Thread.currentThread().getId());
        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            System.out.println("interrupted while sleeping");
        }
    }, 1000, TimeUnit.MILLISECONDS);
    Thread.sleep(10000);
    executor.shutdownNow();
}

当您将任务提交到计划的线程池时,它将使用RunnableScheduledFuture进行包装,并将其传递给delayedExecute方法。如果当前工作人员数小于corePoolSize,此方法会将任务添加到任务队列并启动新工作程序。工作者试图从队列中获取任务并处理它调用run方法。有一个专用的DelayedWorkQueue实现,只有在它们准备好执行时才返回任务。以下是run RunnableScheduledFuture方法的样子:

    /**
     * Overrides FutureTask version so as to reset/requeue if periodic.
     */
    public void run() {
        boolean periodic = isPeriodic();
        if (!canRunInCurrentRunState(periodic))
            cancel(false);
        else if (!periodic)
            ScheduledFutureTask.super.run();
        else if (ScheduledFutureTask.super.runAndReset()) {
            setNextRunTime();
            reExecutePeriodic(outerTask);
        }
    }

正如您所看到的,它在runAndReset中调用实际任务逻辑,计算下一个运行时间并再次向队列提交相同的更新任务(reExecutePeriodic几乎与schedule相同)。对于所有执行只有一个周期性任务,在上一次执行完成后,一次又一次地重新提交更新时间。因此,此类线程池在任何给定时刻仅运行每个任务类型的单个实例,并且仅针对不同类型的任务进行扩展。

如果你对春季计划任务如何看待ScheduledTaskRegistrar类,特别是在scheduleFixedDelayTask方法感兴趣。


0
投票

在您使用threadpool的情况下:默认情况下,您的池中将有10个线程(已初始化)。 @scheduled第一次执行时,这个函数将在你的池中的一个线程中执行(现在剩下9个线程),如果函数已经完成并再次执行@scheduled,你的函数将在你的其他线程中执行你的游泳池,所以现在游泳池里剩下8个线程。 (8个空闲,2个正在运行的线程)

如果您不使用线程池,则只使用一个线程。

弹簧文档:

如果未提供“pool-size”属性,则默认线程池将只有一个线程。调度程序没有其他配置选项。

https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/scheduling.html

© www.soinside.com 2019 - 2024. All rights reserved.