最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java項(xiàng)目實(shí)現(xiàn)定時(shí)任務(wù)的三種方法

 更新時(shí)間:2022年06月13日 09:56:02   作者:dreaming9420  
Java開發(fā)過程中經(jīng)常會(huì)遇到使用定時(shí)任務(wù)的情況,比如在某個(gè)活動(dòng)結(jié)束時(shí),自動(dòng)生成獲獎(jiǎng)名單,導(dǎo)出excel等,下面這篇文章主要給大家介紹了關(guān)于Java項(xiàng)目實(shí)現(xiàn)定時(shí)任務(wù)的三種方法,需要的朋友可以參考下

1 使用java.util.Timer

這種方式的定時(shí)任務(wù)主要用到兩個(gè)類,Timer 和 TimerTask,使用起來比較簡(jiǎn)單。其中 Timer 負(fù)責(zé)設(shè)定 TimerTask 的起始與間隔執(zhí)行時(shí)間。 TimerTask是一個(gè)抽象類,new的時(shí)候?qū)崿F(xiàn)自己的 run 方法,然后將其丟給 Timer 去執(zhí)行即可。

代碼示例:

import java.time.LocalDateTime;
import java.util.Timer;
import java.util.TimerTask;

public class Schedule {
    public static void main(String[] args) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + " 當(dāng)前時(shí)間" + LocalDateTime.now());
            }
        };
        // 在指定延遲0毫秒后開始,隨后地執(zhí)行以2000毫秒間隔執(zhí)行timerTask 
        new Timer().schedule(timerTask, 0L, 2000L);
        System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + " 當(dāng)前時(shí)間" + LocalDateTime.now());
    }
}

缺點(diǎn):

  • Timer 的背后只有一個(gè)線程,不管有多少個(gè)任務(wù),都只有一個(gè)工作線程串行執(zhí)行,效率低下
  • 受限于單線程,如果第一個(gè)任務(wù)邏輯上死循環(huán)了,后續(xù)的任務(wù)一個(gè)都得不到執(zhí)行
  • 依然是由于單線程,任一任務(wù)拋出異常后,整個(gè) Timer 就會(huì)結(jié)束,后續(xù)任務(wù)全部都無(wú)法執(zhí)行

2 使用ScheduledExecutorService

ScheduledExecutorService 即是 Timer 的替代者,JDK 1.5 并發(fā)包引入,是基于線程池設(shè)計(jì)的定時(shí)任務(wù)類。每個(gè)調(diào)度任務(wù)都會(huì)分配到線程池中的某一個(gè)線程去執(zhí)行,任務(wù)就是并發(fā)調(diào)度執(zhí)行的,任務(wù)之間互不影響。

Java 5.0引入了java.util.concurrent包,其中的并發(fā)實(shí)用程序之一是ScheduledThreadPoolExecutor ,它是一個(gè)線程池,用于以給定的速率或延遲重復(fù)執(zhí)行任務(wù)。它實(shí)際上是Timer/TimerTask組合的更通用替代品,因?yàn)樗试S多個(gè)服務(wù)線程,接受各種時(shí)間單位,并且不需要子類TimerTask (只需實(shí)現(xiàn)Runnable)。使用一個(gè)線程配置ScheduledThreadPoolExecutor使其等效于Timer 。

代碼示例:

import java.time.LocalDateTime;
import java.util.concurrent.*;

public class Schedule {
    public static void main(String[] args) {
        // 創(chuàng)建一個(gè)ScheduledThreadPoolExecutor線程池,核心線程數(shù)為5
        ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(5);
        // 創(chuàng)建Runnable打印當(dāng)前線程和當(dāng)前時(shí)間
        Runnable r = () -> System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + " 當(dāng)前時(shí)間" + LocalDateTime.now());
        /**
         * schedule:只執(zhí)行一次調(diào)度
         * scheduleAtFixedRate:一開始就計(jì)算間隔時(shí)間,如果任務(wù)超過間隔時(shí)間,那么就直接開始下一個(gè)任務(wù)
         * scheduleWithFixedDelay:任務(wù)無(wú)論執(zhí)行多久,都要等待上一輪任務(wù)完成之后再間隔指定時(shí)間,然后才開始下一個(gè)任務(wù)
         */
         // 在指定1秒延遲后執(zhí)行r,之后每?jī)擅雸?zhí)行一次
        scheduledExecutorService.scheduleAtFixedRate(r, 1, 2, TimeUnit.SECONDS);
    }
}

3 使用Spring Task

Spring Task 底層是基于 JDK 的 ScheduledThreadPoolExecutor 線程池來實(shí)現(xiàn)的。直接通過Spring 提供的 @Scheduled 注解即可定義定時(shí)任務(wù),非常方便。

以Spring Boot來作為示例,步驟為

  1. 在啟動(dòng)類所在包下創(chuàng)建Schedule 類(在沒有配置@ComponentScan的情況下,Spring Boot只會(huì)默認(rèn)掃描啟動(dòng)類所在包的spring組件)
  2. 在該類上添加@Component和@EnableScheduling注解
  3. 在方法上添加@Scheduled注解,該注解主要參數(shù)如下
String cron() default "";  // 支持cron表達(dá)式

long fixedDelay() default -1;  // 在最后一次調(diào)用結(jié)束和下一次調(diào)用開始之間的時(shí)間間隔,以毫秒為單位
String fixedDelayString() default "";  // 同上,類似ScheduledExecutorService的scheduleWithFixedDelay

long fixedRate() default -1;  // 在調(diào)用之前的時(shí)間間隔,以毫秒為單位
String fixedRateString() default "";  // 同上,類似ScheduledExecutorService的scheduleAtFixedRate

long initialDelay() default -1;  // 在第一次執(zhí)行fixedRate()或fixedDelay()任務(wù)之前要延遲的毫秒數(shù)
String initialDelayString() default "";  // 同上

代碼示例:

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@EnableScheduling
public class Schedule {
    @Scheduled(fixedRate = 2000L)
    public void task() {
        System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + " 當(dāng)前時(shí)間" + LocalDateTime.now());
    }
}

優(yōu)點(diǎn): 簡(jiǎn)單,輕量,支持 Cron 表達(dá)式缺點(diǎn) :默認(rèn)只支持單機(jī),是單線程的,并且提供的功能比較單一

可以通過@EnableAsync和 @Async開啟多線程

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@EnableAsync  // 開啟異步多線程
@EnableScheduling
public class Schedule {

    @Async
    @Scheduled(fixedRate = 2000L)
    public void task() {
        System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + " 當(dāng)前時(shí)間" + LocalDateTime.now());
    }
}

使用@EnableAsync注解后,默認(rèn)情況下,Spring將搜索關(guān)聯(lián)的線程池定義:上下文中的唯一org.springframework.core.task.TaskExecutor
的bean,或者名為“taskExecutor”的java.util.concurrent.Executor
的bean。如果兩者都無(wú)法解析,則將使用org.springframework.core.task.SimpleAsyncTaskExecutor來處理異步方法調(diào)用。

TaskExecutor實(shí)現(xiàn)為每個(gè)任務(wù)啟動(dòng)一個(gè)新線程,異步執(zhí)行它。 支持通過“concurrencyLimit”bean 屬性限制并發(fā)線程。默認(rèn)情況下,并發(fā)線程數(shù)是無(wú)限的,所以使用默認(rèn)的線程池有導(dǎo)致內(nèi)存溢出的風(fēng)險(xiǎn)。

注意:剛才的運(yùn)行結(jié)果看起來是線程復(fù)用的,而實(shí)際上此實(shí)現(xiàn)不重用線程應(yīng)盡量實(shí)現(xiàn)一個(gè)線程池TaskExecutor ,特別是用于執(zhí)行大量短期任務(wù)。不要使用默認(rèn)的SimpleAsyncTaskExecutor。

import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.concurrent.Executor;

@Component
@EnableAsync
@EnableScheduling
public class Schedule {

    @Async
    @Scheduled(fixedRate = 2000L)
    public void task() {
        System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + " 當(dāng)前時(shí)間" + LocalDateTime.now());
    }


    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(10);
        taskExecutor.setMaxPoolSize(50);
        taskExecutor.setQueueCapacity(200);
        taskExecutor.setKeepAliveSeconds(60);
        taskExecutor.setThreadNamePrefix("自定義-");
        taskExecutor.setAwaitTerminationSeconds(60);
        return taskExecutor;
    }
}

上面提到的一些定時(shí)任務(wù)的解決方案都是在單機(jī)下執(zhí)行的,適用于比較簡(jiǎn)單的定時(shí)任務(wù)場(chǎng)景比如每天凌晨備份一次數(shù)據(jù)。如果我們需要一些高級(jí)特性比如支持任務(wù)在分布式場(chǎng)景下的分片和高可用的話,我們就需要用到分布式任務(wù)調(diào)度框架了,比如Quartz、Elastic-Job、XXL-JOB、PowerJob,本文就不再詳細(xì)進(jìn)行介紹了,感興趣的可以自行查閱相關(guān)資料。

總結(jié) 

到此這篇關(guān)于Java項(xiàng)目實(shí)現(xiàn)定時(shí)任務(wù)的三種方法的文章就介紹到這了,更多相關(guān)Java定時(shí)任務(wù)實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于JSON解析中獲取不存在的key問題

    關(guān)于JSON解析中獲取不存在的key問題

    這篇文章主要介紹了關(guān)于JSON解析中獲取不存在的key問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 關(guān)于Java創(chuàng)建線程的2種方式以及對(duì)比

    關(guān)于Java創(chuàng)建線程的2種方式以及對(duì)比

    這篇文章主要給大家介紹了關(guān)于Java創(chuàng)建線程的2種方式以及對(duì)比的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-01-01
  • 實(shí)踐講解SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式

    實(shí)踐講解SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式

    本篇講解了SpringBoot自定義初始化Bean+HashMap優(yōu)化策略模式,通過實(shí)踐的方式更通俗易懂,對(duì)此不了解的同學(xué)跟著小編往下看吧
    2021-09-09
  • Mybatis入門教程之新增、更新、刪除功能

    Mybatis入門教程之新增、更新、刪除功能

    這篇文章給大家介紹了Mybatis進(jìn)行基本的增刪改操作,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下
    2017-02-02
  • SpringMVC攔截器創(chuàng)建配置及執(zhí)行順序

    SpringMVC攔截器創(chuàng)建配置及執(zhí)行順序

    這篇文章主要為大家介紹了SpringMVC攔截器創(chuàng)建配置及執(zhí)行順序,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • BaseDao封裝JavaWeb的增刪改查的實(shí)現(xiàn)代碼

    BaseDao封裝JavaWeb的增刪改查的實(shí)現(xiàn)代碼

    Basedao 是一種基于數(shù)據(jù)訪問對(duì)象(Data Access Object)模式的設(shè)計(jì)方法,它是一個(gè)用于處理數(shù)據(jù)庫(kù)操作的基礎(chǔ)類,負(fù)責(zé)封裝數(shù)據(jù)庫(kù)訪問的底層操作,提供通用的數(shù)據(jù)庫(kù)訪問方法,本文給大家介紹了BaseDao封裝JavaWeb的增刪改查的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2024-03-03
  • java中的編碼轉(zhuǎn)換過程(以u(píng)tf8和gbk為例)

    java中的編碼轉(zhuǎn)換過程(以u(píng)tf8和gbk為例)

    這篇文章主要介紹了java中的編碼轉(zhuǎn)換過程(以u(píng)tf8和gbk為例),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • maven打包本地jar到項(xiàng)目中的方法實(shí)現(xiàn)

    maven打包本地jar到項(xiàng)目中的方法實(shí)現(xiàn)

    本文主要介紹了maven打包本地jar到項(xiàng)目中的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Java實(shí)現(xiàn)批量下載(打包成zip)的實(shí)現(xiàn)

    Java實(shí)現(xiàn)批量下載(打包成zip)的實(shí)現(xiàn)

    這篇文章主要介紹了Java實(shí)現(xiàn)批量下載(打包成zip)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 解答為什么 Java 線程沒有Running狀態(tài)

    解答為什么 Java 線程沒有Running狀態(tài)

    Java 線程沒有Running狀態(tài)指的是一個(gè)在 JVM 中執(zhí)行 的線程處于的狀態(tài),本文小編將為大家詳解一二,需要的朋友可以參考下面文章具體內(nèi)容
    2021-09-09

最新評(píng)論

班戈县| 株洲县| 仁怀市| 凌云县| 平原县| 聊城市| 西昌市| 特克斯县| 上虞市| 石首市| 宝山区| 始兴县| 汤原县| 卢氏县| 永泰县| 宁都县| 大余县| 黑山县| 柳林县| 格尔木市| 保德县| 迭部县| 潞城市| 泸水县| 莫力| 定陶县| 广东省| 霍山县| 阿克陶县| 平乡县| 阜新| 邹平县| 华阴市| 崇州市| 达日县| 南皮县| 北碚区| 昆山市| 修文县| 定西市| 喀喇沁旗|