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

Java定時任務(wù)原理詳解

 更新時間:2022年07月29日 08:29:17   作者:HACKXIYU  
當下,java編碼過程中,實現(xiàn)定時任務(wù)的方式主要以以下兩種為主:spring框架的@Scheduled和quzrtz框架。本文主要就二者的框架原理實現(xiàn)做一個入門引導,為了解深層實現(xiàn)細節(jié)做一定的鋪墊

序章

定時任務(wù)實現(xiàn)方式

當下,java編碼過程中,實現(xiàn)定時任務(wù)的方式主要以以下兩種為主

  • spring框架的@Scheduled
  • quzrtz框架

網(wǎng)絡(luò)上關(guān)于這兩種框架的實踐和配置相關(guān)的教程很多,這里不再贅述。

本文主要就二者的框架原理實現(xiàn)做一個入門引導,為了解深層實現(xiàn)細節(jié)做一定的鋪墊。

本文源碼版本

spring-context-3.2.18.RELEASE.jar

quartz-1.8.6.jar

一、Scheduled

1.1 使用方法

@EnableScheduling // @EnableScheduling 在配置類上使用,開啟計劃任務(wù)的支持
@Component(value="myClass")// 由spring管理
public class MyClass {
 
    @Scheduled(cron= "0 0 0 * * ?")//0 0 12 * * ? 每天12點觸發(fā)0 0 0/1 * * ?  0 0 0 * * ?
    public void myTask() {
        // 業(yè)務(wù)邏輯
        ...
    }
}

1.2 源碼分析

1.2.1 定時任務(wù)執(zhí)行入口在哪?

org.springframework.scheduling.config.ContextLifecycleScheduledTaskRegistrar
 
public void onApplicationEvent(ContextRefreshedEvent event) {
    if (event.getApplicationContext() != this.applicationContext) {
        return;
    }
    // 定時任務(wù)執(zhí)行入口方法綁定到容器生命周期上
    scheduleTasks();
}

1.2.2 調(diào)用鏈路

1. 所有已注冊task

org.springframework.scheduling.config.ScheduledTaskRegistrar
protected void scheduleTasks() {
    ...
    if (this.triggerTasks != null) {
        for (TriggerTask task : this.triggerTasks) {
            // 執(zhí)行初始化完成的task和Trigger
            this.scheduledFutures.add(this.taskScheduler.schedule(
                    task.getRunnable(), task.getTrigger()));
        }
    }
    ...
}

2. 單個task

org.springframework.scheduling.TaskScheduler
ScheduledFuture schedule(Runnable task, Trigger trigger);

3. 線程池執(zhí)行task

org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
public ScheduledFuture schedule(Runnable task, Trigger trigger) {
    ScheduledExecutorService executor = getScheduledExecutor();
    try {
        ErrorHandler errorHandler =
                (this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
        // 調(diào)用具體的實現(xiàn)方法.schedule()
        return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule();
    }
    catch (RejectedExecutionException ex) {
        throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
    }
}

4. 這塊是具體的線程實現(xiàn)細節(jié),已經(jīng)與schedul無關(guān)

private <V> ScheduledFuture<V> schedule(final ScheduledFutureTask<V> task) {
    if (task == null) {
        throw new NullPointerException("task");
    } else {
        if (this.inEventLoop()) {
            this.delayedTaskQueue.add(task);
        } else {
            // 此處就是真正的線程執(zhí)行方法
            this.execute(new Runnable() {
                public void run() {
                    SingleThreadEventExecutor.this.delayedTaskQueue.add(task);
                }
            });
        }
 
        return task;
    }
}

1.2.3 @Scheduled注解的生效原理

org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor
 
// BeanPostProcessor生命周期方法,spring加載的時候會執(zhí)行
public Object postProcessAfterInitialization(final Object bean, String beanName) {
        Class<?> targetClass = AopUtils.getTargetClass(bean);
    if (!this.nonAnnotatedClasses.containsKey(targetClass)) {
        final Set<Method> annotatedMethods = new LinkedHashSet<Method>(1);
        ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
            public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                Scheduled scheduled = AnnotationUtils.getAnnotation(method, Scheduled.class);
                if (scheduled != null) {
                    // @Scheduled的真正解析方法,具體解析細節(jié)和參數(shù)參看源碼
                    // 解析后添加到ScheduledTaskRegistrar里
                    // 全部任務(wù)解析完成,執(zhí)行ScheduledTaskRegistrar,具體實現(xiàn)參看[1.2.2 調(diào)用鏈路]章節(jié)
                    processScheduled(scheduled, method, bean);
                    annotatedMethods.add(method);
                }
            }
        });
        if (annotatedMethods.isEmpty()) {
            this.nonAnnotatedClasses.put(targetClass, Boolean.TRUE);
        }
    }
    return bean;
}

二、QUARTZ

2.1 使用方法

// 實例化一個調(diào)度器工廠,每個應(yīng)用只有唯一一個工廠實例
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
// 實例化一個調(diào)度器
Scheduler sched = schedFact.getScheduler();
// 啟動,只有啟動了調(diào)度器Quartz才會去執(zhí)行任務(wù)
sched.start();
 
// 實例化一個任務(wù)
JobDetail job = newJob(HelloJob.class)
  .withIdentity("myJob", "group1")
  .build();
 
// 實例化一個任務(wù)觸發(fā)器,立刻觸發(fā),每40s執(zhí)行一次
Trigger trigger = newTrigger()
  .withIdentity("myTrigger", "group1")
  .startNow()
  .withSchedule(simpleSchedule()
      .withIntervalInSeconds(40)
      .repeatForever())
  .build();
 
// 調(diào)度任務(wù)
sched.scheduleJob(job, trigger);

2.2 源碼分析

2.2.1 啟動入口

1. web.xml配置

<context-param>
   <param-name>quartz:config-file</param-name>
   <param-value>/some/path/my_quartz.properties</param-value>
</context-param>
<context-param>
   <param-name>quartz:shutdown-on-unload</param-name>
   <param-value>true</param-value>
</context-param>
<context-param>
   <param-name>quartz:start-on-load</param-name>
   <param-value>true</param-value>
</context-param>
 
<listener>
   <listener-class>
       org.quartz.ee.servlet.QuartzInitializerListener
   </listener-class>
</listener>

2. org.quartz.ee.servlet.QuartzInitializerListener

// 執(zhí)行ServletContextListener.contextInitialized的容器生命周期方法
public void contextInitialized(ServletContextEvent sce) {
    ...
    // 根據(jù)自定義的配置文件加載SchedulerFactory
    if (configFile != null) {
        factory = new StdSchedulerFactory(configFile);
    } else {
        factory = new StdSchedulerFactory();
    }
    
    // 加載scheduler
    scheduler = factory.getScheduler();
    
    // 啟動scheduler
    scheduler.start();
    log.info("Scheduler has been started...");
    ...
}   

2.2.2 核心方法詳解

1. StdSchedulerFactory.getScheduler()
public Scheduler getScheduler() throws SchedulerException {
    if (cfg == null) {
        // 根據(jù)不同的配置方式加載對應(yīng)配置
        initialize();
    }
    ... 
    // 加載實例(加載Scheduler整個上下文環(huán)境)
    sched = instantiate();
    return sched;
}

2. StdSchedulerFactory.getScheduler().instantiate()

具體實現(xiàn)代碼很多,以下做偽代碼描述

private Scheduler instantiate() throws SchedulerException {
 
    // 校驗初始化
    if (cfg == null) {
        initialize();
    }
    
    // 獲取 Scheduler
    // 加載 ThreadPool
    // 加載 JobStore
    // 加載 DataSources
    // 加載 SchedulerPlugins
    // 加載 JobListeners
    // 加載 TriggerListeners
    // 加載 ThreadExecutor
    
    // 構(gòu)造QuartzScheduler
    qs = new QuartzScheduler(rsrcs, schedCtxt, idleWaitTime, dbFailureRetry);
    Scheduler scheduler = instantiate(rsrcs, qs);
    qs.initialize();
    
    // 返回實例化好的scheduler
    return scheduler;
}

到此這篇關(guān)于Java定時任務(wù)原理詳解的文章就介紹到這了,更多相關(guān)Java定時任務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java構(gòu)建高效結(jié)果緩存方法示例

    Java構(gòu)建高效結(jié)果緩存方法示例

    這篇文章主要介紹了Java構(gòu)建高效結(jié)果緩存方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • JAVA中的字符串常量池使用操作代碼

    JAVA中的字符串常量池使用操作代碼

    Java中的字符串常量池是Java堆中的一塊特殊存儲區(qū)域,用于存儲字符串。它的實現(xiàn)是為了提高字符串操作的性能并節(jié)省內(nèi)存,這篇文章主要介紹了JAVA中的字符串常量池,需要的朋友可以參考下
    2022-12-12
  • maven引入第三方j(luò)ar包配置詳解

    maven引入第三方j(luò)ar包配置詳解

    這篇文章主要為大家介紹了maven引入第三方j(luò)ar包配置詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • 在Spring 中使用@Aspect 控制自定義注解的操作

    在Spring 中使用@Aspect 控制自定義注解的操作

    這篇文章主要介紹了在Spring 中使用@Aspect 控制自定義注解的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • ApiOperation和ApiParam注解依賴的安裝和使用以及注意事項說明

    ApiOperation和ApiParam注解依賴的安裝和使用以及注意事項說明

    這篇文章主要介紹了ApiOperation和ApiParam注解依賴的安裝和使用以及注意事項說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • java實現(xiàn)MD5加密的方法小結(jié)

    java實現(xiàn)MD5加密的方法小結(jié)

    這篇文章主要介紹了java實現(xiàn)MD5加密的方法,結(jié)合具體實例形式總結(jié)分析了java實現(xiàn)md5加密的常用操作技巧與使用方法,需要的朋友可以參考下
    2017-10-10
  • 使用Spring CROS解決項目中的跨域問題詳解

    使用Spring CROS解決項目中的跨域問題詳解

    這篇文章主要介紹了使用Spring CROS解決項目中的跨域問題詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-01-01
  • .idea文件夾里面iml文件的作用及說明

    .idea文件夾里面iml文件的作用及說明

    這篇文章主要介紹了.idea文件夾里面iml文件的作用及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringBoot使用Redisson實現(xiàn)延遲執(zhí)行的完整示例

    SpringBoot使用Redisson實現(xiàn)延遲執(zhí)行的完整示例

    這篇文章主要介紹了SpringBoot使用Redisson實現(xiàn)延遲執(zhí)行的完整示例,文中通過代碼示例講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-06-06
  • Hibernate中實現(xiàn)增刪改查的步驟詳解

    Hibernate中實現(xiàn)增刪改查的步驟詳解

    本篇文章主要介紹了Hibernate中實現(xiàn)增刪改查的步驟與方法,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02

最新評論

济宁市| 微博| 枝江市| 攀枝花市| 英德市| 宁海县| 南投县| 淳化县| 安多县| 南京市| 西青区| 郴州市| 阿拉善盟| 西和县| 崇左市| 长汀县| 柞水县| 抚顺县| 富民县| 石景山区| 辉县市| 湟中县| 博野县| 佛山市| 正蓝旗| 唐河县| 莫力| 河间市| 哈尔滨市| 镇平县| 永新县| 平和县| 沐川县| 会同县| 新野县| 无棣县| 贺州市| 湘潭市| 栖霞市| 新兴县| 兴业县|