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

淺析java中常用的定時(shí)任務(wù)框架-單體

 更新時(shí)間:2021年12月21日 16:39:42   作者:小伙子vae  
這篇文章主要帶大家了解常用的單體應(yīng)用定時(shí)任務(wù)框架以及掌握定時(shí)任務(wù)在單體中如何使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

一、閱讀收獲

1. 了解常用的單體應(yīng)用定時(shí)任務(wù)框架

2. 掌握定時(shí)任務(wù)在單體中如何使用

二、本章源碼下載

本章源碼下載已分享github

三、Timer+TimerTask

  • 這是jdk自帶的java.util.Timer類,這個(gè)類允許你調(diào)度一個(gè)java.util.TimerTask任務(wù)。
  • 使用這種方式可以讓你的程序按照某一個(gè)頻度執(zhí)行,但不能在指定時(shí)間運(yùn)行,一般用的較少。
/**
 * @Description: 1. Timer+TimerTask:(jdk自帶)
 * 這是java自帶的java.util.Timer類,這個(gè)類允許你調(diào)度一個(gè)java.util.TimerTask任務(wù)。
 * 使用這種方式可以讓你的程序按照某一個(gè)頻度執(zhí)行,但不能在指定時(shí)間運(yùn)行。一般用的較少。
 * @Author: jianweil
 * @date: 2021/12/14 13:36
 */
public class TimerTest {
    public static void main(String[] args) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("task  run:" + new Date());
            }
        };

        TimerTask timerTask2 = new TimerTask() {
            @Override
            public void run() {
                System.out.println("task2  run:" + new Date());
                //多線程并行處理定時(shí)任務(wù)時(shí),Timer運(yùn)行多個(gè)TimeTask時(shí),只要其中之一沒有捕獲拋出的異常,其它任務(wù)便會(huì)自動(dòng)終止運(yùn)行,使用ScheduledExecutorService則沒有這個(gè)問題。
                int i = 1/0;
            }
        };
        //idea會(huì)提示:使用ScheduledExecutorService代替Timer吧
        Timer timer = new Timer();
        System.out.println("begin:" + new Date());
        //安排指定的任務(wù)在指定的時(shí)間開始進(jìn)行重復(fù)的固定延遲執(zhí)行。這里是延遲5秒開始執(zhí)行,之后每3秒執(zhí)行一次
        timer.schedule(timerTask, 5000, 3000);
        timer.schedule(timerTask2, 5000, 3000);
    }


}

多線程并行處理定時(shí)任務(wù)時(shí),Timer運(yùn)行多個(gè)TimeTask時(shí),只要其中之一沒有捕獲拋出的異常,其它任務(wù)便會(huì)自動(dòng)終止運(yùn)行,使用ScheduledExecutorService則沒有這個(gè)問題。

四、ScheduledExecutorService

ScheduledExecutorService也是jdk自帶的定時(shí)類,可以替代Timer

package com.ljw.springboottimer.scheduledExecutorservice;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;

import java.util.Date;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 2. ScheduledExecutorService代替Timer(jdk自帶)
 * 多線程并行處理定時(shí)任務(wù)時(shí),Timer運(yùn)行多個(gè)TimeTask時(shí),只要其中之一沒有捕獲拋出的異常,其它任務(wù)便會(huì)自動(dòng)終止運(yùn)行,
 * 使用ScheduledExecutorService則沒有這個(gè)問題。
 * @Author: jianweil
 * @date: 2021/12/14 13:42
 */
public class ScheduledExecutorServiceTest {
    public static void main(String[] args) throws InterruptedException {

        //當(dāng)所有的非守護(hù)線程結(jié)束時(shí),程序也就終止了,同時(shí)會(huì)殺死進(jìn)程中的所有守護(hù)線程。反過來說,只要任何非守護(hù)線程還在運(yùn)行,程序就不會(huì)終止。
        ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
                new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(false).build());
        System.out.println("begin:" + new Date());
        // 參數(shù):1、任務(wù)體 2、首次執(zhí)行的延時(shí)時(shí)間 3、任務(wù)執(zhí)行間隔 4、間隔時(shí)間單位
        //延遲5秒執(zhí)行,之后每3秒執(zhí)行一次
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                //do something
                System.out.println("begin:" + new Date());
            }
        }, 5, 3, TimeUnit.SECONDS);
    }
}

五、Spring Task

spring提供的類,可引入依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

開啟定時(shí)任務(wù):@EnableScheduling

使用:在相應(yīng)的任務(wù)方法前加上注解@Scheduled即可

5.1 單線程串行執(zhí)行-@Scheduled

@Scheduled注解默認(rèn)使同一個(gè)線程中串行執(zhí)行,如果只有一個(gè)定時(shí)任務(wù),這樣做肯定沒問題,當(dāng)定時(shí)任務(wù)增多,如果一個(gè)任務(wù)卡死,會(huì)導(dǎo)致其他任務(wù)也無法執(zhí)行。

業(yè)務(wù)測(cè)試:

@Component
@EnableScheduling
public class SpringTaskTest {
    @Scheduled(cron = "0/5 * * * * *")
    public void run() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "=====>>>>>使用cron  {}" + (System.currentTimeMillis() / 1000));
    }
} 

5.2 多線程并發(fā)運(yùn)行-@Scheduled+配置定時(shí)器的程池(推薦)

  • 解決單線程串行執(zhí)行任務(wù)的問題,需要配置定時(shí)器的程池,推薦這種方法
  • 配置并注入一個(gè)TaskScheduler類bean即可
  • 配置定時(shí)器的線程池類如下:
package com.ljw.springboottimer.springtask;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

/**
 * @Description: 解決單線程串行執(zhí)行 方式2:@Scheduled+配置定時(shí)器的線程池
 * @Author: jianweil
 * @date: 2021/12/14 14:44
 */
@Configuration
public class TaskSchedulerConfig {
    /**
     * 初始化了一個(gè)線程池大小為 5  的 TaskScheduler, 避免了所有任務(wù)都用一個(gè)線程來執(zhí)行
     *
     * @return
     */
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(5);
        taskScheduler.setThreadNamePrefix("TaskSchedulerConfig-ljw");
        return taskScheduler;
    }
}

業(yè)務(wù)測(cè)試

@Component
@EnableScheduling
public class SpringTaskTest {

    @Scheduled(cron = "0/5 * * * * *")
    public void run() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "=====>>>>>使用cron  {}" + (System.currentTimeMillis() / 1000));
    }
    
    @Scheduled(fixedRate = 5000)
    public void run1() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "=====>>>>>使用fixedRate  {}" + (System.currentTimeMillis() / 1000));
    }

} 

5.3 多線程并發(fā)執(zhí)行-@Scheduled+@Async+配置異步線程池

解決單線程串行執(zhí)行任務(wù)的問題,也可以結(jié)合異步注解@Async實(shí)現(xiàn),但這種方法并不推薦,需要兩個(gè)注解,代碼編寫的工作量大

還可以解決fixedRate在遇到某些執(zhí)行任務(wù)時(shí)間超過配置的時(shí)間隔,下次任務(wù)時(shí)間到了還要等待上次任務(wù)執(zhí)行完成的情況,這是3.2不能解決的。

配置異步線程池類如下:

package com.ljw.springboottimer.springtask;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Description: 解決單線程串行執(zhí)行 方式1:@Scheduled+@Async+配置異步線程池
 * @Author: jianweil
 * @date: 2021/12/14 14:35
 */
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    /**
     * 定義@Async默認(rèn)的線程池
     * ThreadPoolTaskExecutor不是完全被IOC容器管理的bean,可以在方法上加上@Bean注解交給容器管理,這樣可以將taskExecutor.initialize()方法調(diào)用去掉,容器會(huì)自動(dòng)調(diào)用
     *
     * @return
     */
    @Override
    public Executor getAsyncExecutor() {
        int processors = Runtime.getRuntime().availableProcessors();
        //常用的執(zhí)行器
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //核心線程數(shù)
        taskExecutor.setCorePoolSize(10);
        taskExecutor.setMaxPoolSize(50);
        //線程隊(duì)列最大線程數(shù),默認(rèn):50
        taskExecutor.setQueueCapacity(100);
        //線程名稱前綴
        taskExecutor.setThreadNamePrefix("AsyncConfig-ljw-");
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //執(zhí)行初始化(重要)
        taskExecutor.initialize();
        return taskExecutor;
    }
}

業(yè)務(wù)測(cè)試需要加上@Async注解

@Component
@EnableScheduling
public class SpringTaskTest {

    @Scheduled(cron = "0/5 * * * * *")
    @Async
    public void run() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "=====>>>>>使用cron  {}" + (System.currentTimeMillis() / 1000));
    }
    
    @Scheduled(fixedRate = 5000)
    @Async
    public void run1() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "=====>>>>>使用fixedRate  {}" + (System.currentTimeMillis() / 1000));
    }

} 

如果同時(shí)配置了3.2配置定時(shí)器的程池和3.3配置異步線程池,并且注解使用了@Scheduled+@Async,則定時(shí)任務(wù)使用的線程池為:配置異步線程池

5.4 @Scheduled參數(shù)解析

cron:通過cron表達(dá)式來配置任務(wù)執(zhí)行時(shí)間(默認(rèn)是fixedDelay)

initialDelay :定義該任務(wù)延遲多少時(shí)間才開始第一次執(zhí)行

fixedRate:定義一個(gè)按一定頻率執(zhí)行的定時(shí)任務(wù)。fixedRate 每次任務(wù)結(jié)束后會(huì)從任務(wù)編排表中找下一次該執(zhí)行的任務(wù),判斷是否到時(shí)機(jī)執(zhí)行,fixedRate的任務(wù)某次執(zhí)行時(shí)間再長(zhǎng)也不會(huì)造成兩次任務(wù)實(shí)例同時(shí)執(zhí)行,也要等到上次任務(wù)完成,判斷是否到時(shí)機(jī)執(zhí)行,到就立即執(zhí)行,與線程池?zé)o關(guān),除非用了@Async注解,使方法異步,即是使用5.3步驟的配置。(5.2是配置線程池,達(dá)不到效果)

fixedDelay:定義一個(gè)按一定頻率執(zhí)行的定時(shí)任務(wù)。fixedDelay總是在前一次任務(wù)完成后,延時(shí)固定時(shí)間長(zhǎng)度然后再執(zhí)行下一次任務(wù)

六、Quartz

在開發(fā)Quartz相關(guān)應(yīng)用時(shí),只要定義了Job(任務(wù)),JobDetail(任務(wù)描述),Trigger(觸發(fā)器)和Scheduler(調(diào)度器),即可實(shí)現(xiàn)一個(gè)定時(shí)調(diào)度能力。

如果SpringBoot版本是2.0.0以后的,則在spring-boot-starter中已經(jīng)包含了quart的依賴,則可以直接引入依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

6.1. 創(chuàng)建任務(wù)類

方式1:實(shí)現(xiàn)Job類的execute方法即可實(shí)現(xiàn)一個(gè)任務(wù)(推薦)

任務(wù)1如下:

package com.ljw.springboottimer.quartz.do1;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;

/**
 * @Description: 我的定時(shí)任務(wù)-方法1
 * @Author: jianweil
 * @date: 2021/12/14 16:06
 */
public class MyTaskService1 implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println(Thread.currentThread().getName() + "------ Job ------" + new Date());
    }
}

方式2:繼承QuartzJobBean類重寫方法即可實(shí)現(xiàn)一個(gè)任務(wù)

任務(wù)2如下:

package com.ljw.springboottimer.quartz.do1;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.Date;

/**
 * @Description: 我的定時(shí)任務(wù)-方法2
 * @Author: jianweil
 * @date: 2021/12/14 16:06
 */
public class MyTaskService2 extends QuartzJobBean {

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        System.out.println(Thread.currentThread().getName() + "---QuartzJobBean-----" + new Date());
    }
}

6.2. 配置任務(wù)描述和觸發(fā)器

配置類要分別要為每個(gè)任務(wù)聲明兩個(gè)bean

  • 1.JobDetail(任務(wù)描述)
  • 2.Trigger(觸發(fā)器)

配置調(diào)度器信息使用SimpleScheduleBuilder或者CronScheduleBuilder

package com.ljw.springboottimer.quartz.do1;

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Date;

/**
 * @Description: 每個(gè)任務(wù)都要兩步配置
 * 1.配置任務(wù)描述JobDetail 2. 配置觸發(fā)器Trigger
 * @Author: jianweil
 * @date: 2021/12/14 16:08
 */
@Configuration
public class QuartzConfig {

    /**
     * 創(chuàng)建任務(wù)1的 JobDetail1
     *
     * @return
     */
    @Bean
    public JobDetail teatQuartzDetail1() {
        return JobBuilder.newJob(MyTaskService1.class)
                //job的描述
                .withDescription("this is a job1")
                //job 的name和group
                .withIdentity("myTrigger1", "myTriggerGroup1")
                .storeDurably().build();
    }

    /**
     * 創(chuàng)建任務(wù)2的 JobDetail2
     *
     * @return
     */
    @Bean
    public JobDetail teatQuartzDetail2() {
        return JobBuilder.newJob(MyTaskService2.class)
                //job的描述
                .withDescription("this is a job2")
                //job 的name和group
                .withIdentity("myTrigger2", "myTriggerGroup2")
                .storeDurably().build();
    }

    /**
     * 創(chuàng)建任務(wù)1的 Trigger1
     *
     * @return
     */
    @Bean
    public Trigger testQuartzTrigger1() {
        //使用SimpleScheduleBuilder或者CronScheduleBuilder
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                //設(shè)置時(shí)間周期單位秒
                .withIntervalInSeconds(10)
                .repeatForever();

        //兩秒執(zhí)行一次,Quartz表達(dá)式,支持各種牛逼表達(dá)式
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/3 * * * * ?");
        //任務(wù)運(yùn)行的時(shí)間,SimpleSchedle類型觸發(fā)器有效,3秒后啟動(dòng)任務(wù)
        long time = System.currentTimeMillis() + 3 * 1000L;
        Date statTime = new Date(time);


        return TriggerBuilder.newTrigger()
                .withDescription("")
                .forJob(teatQuartzDetail1())
                .withIdentity("myTrigger1", "myTriggerGroup1")
                //默認(rèn)當(dāng)前時(shí)間啟動(dòng)
                .startAt(statTime)
                .withSchedule(cronScheduleBuilder)
                //.withSchedule(scheduleBuilder)
                .build();

    }

    /**
     * 創(chuàng)建任務(wù)2的 Trigger2
     *
     * @return
     */
    @Bean
    public Trigger testQuartzTrigger2() {
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                //設(shè)置時(shí)間周期單位秒
                .withIntervalInSeconds(10)
                .repeatForever();
        return TriggerBuilder.newTrigger()
                .forJob(teatQuartzDetail2())
                .withIdentity("myTrigger2", "myTriggerGroup2")
                .withSchedule(scheduleBuilder)
                .build();
    }

} 

以上就是淺析java中常用的定時(shí)任務(wù)框架-單體的詳細(xì)內(nèi)容,更多關(guān)于java定時(shí)任務(wù)框架的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

安平县| 库伦旗| 安远县| 彩票| 信丰县| 九龙坡区| 余庆县| 四会市| 岳阳市| 普安县| 祁阳县| 新巴尔虎右旗| 施秉县| 贵溪市| 凤阳县| 红桥区| 汽车| 辰溪县| 大安市| 昌吉市| 广宗县| 海原县| 威远县| 鲁山县| 阿坝| 邻水| 班戈县| 六安市| 外汇| 长丰县| 乌什县| 安西县| 沂水县| 唐山市| 临安市| 阳泉市| 佳木斯市| 德阳市| 千阳县| 江口县| 哈巴河县|