欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

@Scheduled定時(shí)器使用注意事項(xiàng)及說(shuō)明

 更新時(shí)間:2024年08月22日 10:25:57   作者:200.OK  
這篇文章主要介紹了@Scheduled定時(shí)器使用注意事項(xiàng)及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

@Scheduled定時(shí)器使用注意事項(xiàng)

首先定時(shí)器可以固定執(zhí)行時(shí)間使用cron表達(dá)式,也可以控制方法執(zhí)行的間隔時(shí)間fixedDelay,這里使用的是cron,創(chuàng)建了schedule包,將定時(shí)任務(wù)放在了schedule包下,下面開(kāi)始進(jìn)入正題。

一般在程序中直接使用定時(shí)器,但是最好設(shè)置一下JVM的默認(rèn)時(shí)區(qū),因?yàn)镴VM默認(rèn)時(shí)區(qū)可能和本機(jī)時(shí)區(qū)不一樣,不同操作系統(tǒng)默認(rèn)時(shí)區(qū)可能不一樣。

使用靜態(tài)變量static聲明的靜態(tài)變量具有全局作用域,對(duì)全局造成影響,保證系統(tǒng)整個(gè)時(shí)區(qū)一致

如果只想針對(duì)某部分設(shè)置時(shí)區(qū)需要顯示指定時(shí)區(qū),不影響全局結(jié)果

package com.test.hello.task;

import com.test.hello.service.TestEntityService;
import com.test.hello.service.TestOneEntityService;
import com.test.hello.service.TestTwoEntityService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;

@Slf4j
@Component
public class TestTask {

    //全局修改時(shí)區(qū),設(shè)置JVM的默認(rèn)時(shí)區(qū),影響整個(gè) Java 虛擬機(jī)中所有涉及日期和時(shí)間的操作所使用的時(shí)區(qū)。
    //在Java中,通過(guò) TimeZone.setDefault() 方法可以實(shí)現(xiàn)對(duì) JVM 默認(rèn)時(shí)區(qū)的修改。
    static {
        TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
    }

    //顯示指定時(shí)區(qū),不影響全局
    // 顯式指定使用的時(shí)區(qū)為 GMT+8
    ZoneId zoneId = ZoneId.of("GMT+8");

    // 獲取當(dāng)前時(shí)間
    LocalDateTime currentTime = LocalDateTime.now(zoneId);

    // 格式化日期時(shí)間
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    String formattedTime = currentTime.format(formatter);



    @Autowired
    private TestEntityService testEntityService;

    @Autowired
    private TestOneEntityService testOneEntityService;

    @Autowired
    private TestTwoEntityService testTwoEntityService;


    /**
     * 每天的00:00:00執(zhí)行任務(wù)
     */
    @Scheduled(cron = "0 0 0 * * *")
    public void scheduled() {
        log.info("=====>>>>>使用cron  {}", testEntityService.countSum());
    }

    @Scheduled(cron = "0 0/1 * * * ?")
    public void scheduledStatisticsOnAboardNum() {
        log.info("=====>>>>>統(tǒng)計(jì): 使用cron  {}", testEntityService.countSum());
        log.info("=====>>>>>)統(tǒng)計(jì): 使用cron  {}", testOneEntityService.countSum());
        log.info("=====>>>>>合計(jì)統(tǒng)計(jì): 使用cron  {}", testTwoEntityService.countSum());
    }


}

為了美觀性,每個(gè)定時(shí)都單獨(dú)放在一個(gè)類(lèi),類(lèi)目以功能+Schedule結(jié)尾,該類(lèi)加上@Component表示交給spring管理,定時(shí)器的表達(dá)式可以在nacos中聲明,防止后期需要改定時(shí)任務(wù)的時(shí)候頻繁修改代碼,只需要修改nacos配置文件即可(nacos配置文件中聲明定時(shí)器名字的時(shí)候不得以特殊字符開(kāi)頭,不然會(huì)報(bào)錯(cuò)踩坑)

package com.test.stats.schedule;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;


@Component
@Slf4j
public class TestSchedule {

    //定時(shí)器表達(dá)式配置在nacos中
    @Scheduled(cron = "${testSchedule.oneCron}")
    //單獨(dú)配置線(xiàn)程池
    @Async("PoolThread")
    public void testScheduled() {
      //定時(shí)器執(zhí)行的邏輯代碼
    }
}

以上代碼使用到了 @Async異步注解,這里我使用了一個(gè)線(xiàn)程池,可以根據(jù)自己的業(yè)務(wù)需求自行決定。

定義線(xiàn)程池的意義在與所有執(zhí)行定時(shí)器都是副線(xiàn)程執(zhí)行,不影響主線(xiàn)程。

使用線(xiàn)程池的情況

  • 異步執(zhí)行任務(wù): 任務(wù)在后臺(tái)異步執(zhí)行,不阻塞當(dāng)前線(xiàn)程或應(yīng)用程序的其他部分時(shí),使用線(xiàn)程池。例如,處理異步消息、發(fā)送電子郵件、執(zhí)行后臺(tái)計(jì)算等。
  • 提高并發(fā)性: 程序需要同時(shí)處理多個(gè)并發(fā)任務(wù)時(shí),線(xiàn)程池可以有效地管理和分配系統(tǒng)資源,提高系統(tǒng)的并發(fā)性和性能。這對(duì)于處理大量獨(dú)立的任務(wù)或請(qǐng)求非常有用。
  • 避免線(xiàn)程創(chuàng)建和銷(xiāo)毀的開(kāi)銷(xiāo): 線(xiàn)程的創(chuàng)建和銷(xiāo)毀通常會(huì)帶來(lái)較大的開(kāi)銷(xiāo)。通過(guò)使用線(xiàn)程池,可以避免頻繁地創(chuàng)建和銷(xiāo)毀線(xiàn)程,而是重用現(xiàn)有線(xiàn)程,減少資源開(kāi)銷(xiāo)。
  • 限制資源使用: 使用線(xiàn)程池可以限制同時(shí)執(zhí)行的任務(wù)數(shù)量,以控制系統(tǒng)資源的使用。這對(duì)于避免系統(tǒng)過(guò)度負(fù)載或資源耗盡非常重要。
  • 任務(wù)隊(duì)列管理: 線(xiàn)程池通常具有任務(wù)隊(duì)列,可以將需要執(zhí)行的任務(wù)添加到隊(duì)列中。這使得任務(wù)按照預(yù)定的順序執(zhí)行,而無(wú)需手動(dòng)管理線(xiàn)程的執(zhí)行。

總結(jié):

如果定時(shí)器執(zhí)行的比較頻繁,不想每次都new線(xiàn)程,而且內(nèi)次都從線(xiàn)程池里取線(xiàn)程,用完線(xiàn)程池自己根據(jù)GC回收機(jī)制銷(xiāo)毀,可以考慮編寫(xiě)線(xiàn)程池

線(xiàn)程池代碼

package com.test.hello.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class ThreadPoolTaskConfig {


    //這里的命名可以在報(bào)錯(cuò)的時(shí)候清楚是哪個(gè)線(xiàn)程報(bào)錯(cuò)了
    @Bean("PoolThread")
    public ThreadPoolTaskExecutor threadPoolWorkTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //線(xiàn)程池創(chuàng)建的核心線(xiàn)程數(shù),線(xiàn)程池維護(hù)線(xiàn)程的最少數(shù)量,即使沒(méi)有任務(wù)需要執(zhí)行,也會(huì)一直存活
        executor.setCorePoolSize(8);
        //如果設(shè)置allowCoreThreadTimeout=true(默認(rèn)false)時(shí),核心線(xiàn)程會(huì)超時(shí)關(guān)閉
        //executor.setAllowCoreThreadTimeOut(true);
        //阻塞隊(duì)列 當(dāng)核心線(xiàn)程數(shù)達(dá)到最大時(shí),新任務(wù)會(huì)放在隊(duì)列中排隊(duì)等待執(zhí)行
        executor.setQueueCapacity(124);
        //最大線(xiàn)程池?cái)?shù)量,當(dāng)線(xiàn)程數(shù)>=corePoolSize,且任務(wù)隊(duì)列已滿(mǎn)時(shí)。線(xiàn)程池會(huì)創(chuàng)建新線(xiàn)程來(lái)處理任
        //任務(wù)隊(duì)列已滿(mǎn)時(shí), 且當(dāng)線(xiàn)程數(shù)=maxPoolSize,,線(xiàn)程池會(huì)拒絕處理任務(wù)而拋出異常
        executor.setMaxPoolSize(64);
        //當(dāng)線(xiàn)程空閑時(shí)間達(dá)到keepAliveTime時(shí),線(xiàn)程會(huì)退出,直到線(xiàn)程數(shù)量=corePoolSize
        //允許線(xiàn)程空閑時(shí)間30秒,當(dāng)maxPoolSize的線(xiàn)程在空閑時(shí)間到達(dá)的時(shí)候銷(xiāo)毀
        //如果allowCoreThreadTimeout=true,則會(huì)直到線(xiàn)程數(shù)量=0
        executor.setKeepAliveSeconds(30);
        //spring 提供的 ThreadPoolTaskExecutor 線(xiàn)程池,是有setThreadNamePrefix() 方法的。
        //jdk 提供的ThreadPoolExecutor 線(xiàn)程池是沒(méi)有 setThreadNamePrefix() 方法的
        executor.setThreadNamePrefix("PoolThread");
        // rejection-policy:拒絕策略:當(dāng)線(xiàn)程數(shù)已經(jīng)達(dá)到maxSize的時(shí)候,如何處理新任務(wù)
        // CallerRunsPolicy():交由調(diào)用方線(xiàn)程運(yùn)行,比如 main 線(xiàn)程;如果添加到線(xiàn)程池失敗,那么主線(xiàn)程會(huì)自己去執(zhí)行該任務(wù),不會(huì)等待線(xiàn)程池中的線(xiàn)程去執(zhí)行
        // AbortPolicy():該策略是線(xiàn)程池的默認(rèn)策略,如果線(xiàn)程池隊(duì)列滿(mǎn)了丟掉這個(gè)任務(wù)并且拋出RejectedExecutionException異常。
        // DiscardPolicy():如果線(xiàn)程池隊(duì)列滿(mǎn)了,會(huì)直接丟掉這個(gè)任務(wù)并且不會(huì)有任何異常
        // DiscardOldestPolicy():丟棄隊(duì)列中最老的任務(wù),隊(duì)列滿(mǎn)了,會(huì)將最早進(jìn)入隊(duì)列的任務(wù)刪掉騰出空間,再?lài)L試加入隊(duì)列
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        executor.initialize();
        return executor;
    }

}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論