簡體   English   中英

Spring Java @Scheduling配置

[英]Spring Java @Scheduling configuration

使用@Scheduling在@Scheduled(fixedRate = 10000)運行方法,並通過實現SchedulingConfigurer設置@Scheduling線程

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

如果我使用Thread.sleep或Lock,則執行器不會創建其他線程,除非Thread.sleep喚醒或鎖定被清除。

有人可以解釋內部工作,如果我有10個池大小,則應以10000毫秒的速率創建10個線程。

在使用線程池的情況下:默認情況下,您的池中將有10個線程(已經初始化)。 第一次執行@scheduled時,此函數將在您的池中的一個線程中執行(現在剩下9個線程),如果該函數尚未完成並且再次執行@scheduled,則您的函數將在另一個線程中執行您的池,因此現在池中還剩下8個線程。 (8個空閑,2個正在運行的線程)

如果您不使用線程池,則僅使用一個線程。

春季文件:

如果不提供“ pool-size”屬性,則默認線程池將只有一個線程。 調度程序沒有其他配置選項。

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

基本上,此類行為來自Spring內部在使用的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數小於corePoolSize ,則此方法將任務添加到任務隊列並啟動新工作corePoolSize Worker嘗試從隊列中獲取任務並通過調用run方法對其run處理。 有一個專用的DelayedWorkQueue實現,僅當任務准備好執行時才返回任務。 這是RunnableScheduledFuture run方法如下所示:

    /**
     * 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調用實際的任務邏輯,計算下一個運行時間,然后將相同的更新任務再次提交到隊列( reExecutePeriodicschedule幾乎相同)。 對於所有執行,只有一個周期性任務,該任務會在前一次執行完成后以更新的時間一次又一次地重新提交。 因此,此類線程池在任何給定時刻僅運行每種任務類型的單個實例,並且僅針對不同類型的任務進行擴展。

如果您對春季計划任務的方式感興趣,請查看ScheduledTaskRegistrar類,尤其是scheduleFixedDelayTask方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM