精华内容
下载资源
问答
  • 解决使用@Scheduled创建任务无法在同一时间执行多个任务的BUG   最近在项目中需要任务调度框架,正好springboot集成了一个简单定时调度,而且我们项目功能比较简单就没必要引入Quartz这种比较大型的框架。但是...

    解决使用@Scheduled创建任务时无法在同一时间执行多个任务的BUG 

           最近在项目中需要任务调度框架,正好springboot集成了一个简单定时调度,而且我们项目功能比较简单就没必要引入Quartz这种比较大型的框架。但是在使用的过程中测试人员发现如果多个任务设计同一时间执行会出现只有一个任务在执行其它任务都无法执行的情况。因为问题比较严重就专门研究了一翻,发现问题还真存在。以下是测试流程:

    1.新建个测试类,里面定义2个方法execute1和execute2。两个方法里面没有任何操作只打印当前时间和线程名,为了模拟线上的情况让该方法运行的时候sleep 1秒再结束(业务操作需要耗费一定的时间)。

    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    import java.time.LocalDateTime;
    
    @Component
    public class MyScheduled {
    
        @Scheduled(cron = "0/5 * * * * ?")
        public void execute1(){
            String curName = Thread.currentThread().getName() ;
            System.out.println("当前时间:"+LocalDateTime.now()+"  任务execute1对应的线程名: "+curName);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        @Scheduled(cron = "0/5 * * * * ?")
        public void execute2(){
    
            String curName = Thread.currentThread().getName() ;
            System.out.println("当前时间:"+LocalDateTime.now()+"  任务execute2对应的线程名: "+curName);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    *因为项目使用的是springboot框架为了让定时任务生效需要在类上面加上@EnableScheduling以开启对定时任务的支持

    按正常的理解此时运行exect1和execute2打印的线程名应该不一致才对,但是测试的结果让人大跌眼镜。以下是本地的运行结果:

     

    当前时间:2018-08-26T10:53:40.123  任务execute1对应的线程名: pool-1-thread-1
    当前时间:2018-08-26T10:53:41.127  任务execute2对应的线程名: pool-1-thread-1
    当前时间:2018-08-26T10:53:45.014  任务execute2对应的线程名: pool-1-thread-1
    当前时间:2018-08-26T10:53:46.028  任务execute1对应的线程名: pool-1-thread-1
    当前时间:2018-08-26T10:53:50.016  任务execute2对应的线程名: pool-1-thread-1
    当前时间:2018-08-26T10:53:51.029  任务execute1对应的线程名: pool-1-thread-1

    可以发现正如测试同事说的那样,同一时间间隔的2个定时任务(都设置了5秒运行一次)只会运行一个,并且神奇的一点时线程名字是一样的。因此有理由怀疑springboot创建线程的时使用了newSingleThreadExecutor。带着这个疑问,我们只能一步步来debug了,我们首先在execute1方法中打个断点看下调用类和线程池看下是什么情况。

    通过上图我们可以发现springboot创建的线程池poolSize确实是1,当前活动线程数(activethreads)为1。我们继续往下跟踪,首先我们从@EnableScheduling这个注解开始跟踪。

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Import({SchedulingConfiguration.class})
    @Documented
    public @interface EnableScheduling {
    }

    可以看到EnableScheduling是将SchedulingConfiguration这个类实例化并注入到springboot容器中,我们继续跟踪下去看下改配置类执行什么操作。

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package org.springframework.scheduling.annotation;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Role;
    
    @Configuration
    @Role(2)
    public class SchedulingConfiguration {
        public SchedulingConfiguration() {
        }
    
        @Bean(
            name = {"org.springframework.context.annotation.internalScheduledAnnotationProcessor"}
        )
        @Role(2)
        public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
            return new ScheduledAnnotationBeanPostProcessor();
        }
    }

    可以看出里面注入了org.springframework.context.annotation.internalScheduledAnnotationProcessor这个类(*这里发现一个@Role(2)注解,没找到这个注解到底实现什么功能)

    然后在springboot的API中查找下这个类到底实现什么功能http://fanyi.baidu.com/transpage?from=auto&to=zh&query=https%3A%2F%2Fdocs.spring.io%2Fspring-framework%2Fdocs%2Fcurrent%2Fjavadoc-api%2Forg%2Fspringframework%2Fscheduling%2Fannotation%2FScheduledAnnotationBeanPostProcessor.html&source=url&ie=utf8&render=1&aldtype=16047(英文不好这里只好使用百度翻译一下)

    大概的意思是如果没有指定TaskScheduler则会创建一个单线程的默认调度器。因此问题就清楚了,需要自己创建一个TaskScheduler。立马百度一下,发现很简单

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(50);
        return taskScheduler;
    }

    只需要把这一段代码放进启动类即可。我这边为了方便就直接放进MySchedule类里面,修改后的代码为:

    import org.springframework.context.annotation.Bean;
    import org.springframework.scheduling.TaskScheduler;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
    import org.springframework.stereotype.Component;
    
    import java.time.LocalDateTime;
    
    @Component
    @EnableScheduling
    public class MyScheduled {
    
        @Bean
        public TaskScheduler taskScheduler() {
            ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
            taskScheduler.setPoolSize(50);
            return taskScheduler;
        }
    
        @Scheduled(cron = "0/5 * * * * ?")
        public void execute1(){
            String curName = Thread.currentThread().getName() ;
            System.out.println("当前时间:"+LocalDateTime.now()+"  任务execute1对应的线程名: "+curName);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        @Scheduled(cron = "0/5 * * * * ?")
        public void execute2(){
    
            String curName = Thread.currentThread().getName() ;
            System.out.println("当前时间:"+LocalDateTime.now()+"  任务execute2对应的线程名: "+curName);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

     

    我们再次测试下效果:

    当前时间:2018-08-26T12:09:50.010  任务execute2对应的线程名: taskScheduler-1
    当前时间:2018-08-26T12:09:50.010  任务execute1对应的线程名: taskScheduler-2
    当前时间:2018-08-26T12:09:55.001  任务execute1对应的线程名: taskScheduler-3
    当前时间:2018-08-26T12:09:55.001  任务execute2对应的线程名: taskScheduler-1
    当前时间:2018-08-26T12:10:00.017  任务execute2对应的线程名: taskScheduler-2
    当前时间:2018-08-26T12:10:00.018  任务execute1对应的线程名: taskScheduler-4
    当前时间:2018-08-26T12:10:05.001  任务execute1对应的线程名: taskScheduler-3
    当前时间:2018-08-26T12:10:05.001  任务execute2对应的线程名: taskScheduler-1

    发现线程名变了,因此问题得到了完美解决。后来继续debug发现ScheduledTaskRegistrar 里面有这么一行代码

    可以发现当taskScheduler对象为空时默认创建的是newSingleThreadScheduledExecutor()  至此问题解决。但是还有以下2个问题后续有空需要继续研究

    1.springboot为啥默认创建的是newSingleThreadScheduledExecutor?

    2.@Role注解到底有什么用处

     

           经过这一折腾,感觉自己对springboot的理解还不够深入,希望在项目中一边踩坑一边研究。后期打算集成quartz+mysql+ZK实现高可用的任务调度,当然这是后话目前还是先把项目做好!

    展开全文
  • celery定时任务简单使用

    万次阅读 2018-07-06 14:38:30
    我们通常使用它来实现异步任务( async task )和定时任务( crontab )。 异步任务比如是发送邮件、或者文件上传, 图像处理等等一些比较耗时的操作 ,定时任务是需要在特定时间执行的任务。它的架构组成如下图: ...

    celery介绍

    Celery 是一个强大的分布式任务队列,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。我们通常使用它来实现异步任务( async task )和定时任务( crontab )。 异步任务比如是发送邮件、或者文件上传, 图像处理等等一些比较耗时的操作 ,定时任务是需要在特定时间执行的任务。它的架构组成如下图:

    celery架构图

    • 任务队列

    任务队列是一种跨线程、跨机器工作的一种机制.

    任务队列中包含称作任务的工作单元。有专门的工作进程持续不断的监视任务队列,并从中获得新的任务并处理.

    • 任务模块

    包含异步任务和定时任务。其中,异步任务通常在业务逻辑中被触发并发往任务队列,而定时任务由 Celery Beat 进程周期性地将任务发往任务队列。

    • 消息中间件 Broker

    Broker ,即为任务调度队列,接收任务生产者发来的消息(即任务),将任务存入队列。 Celery 本身不提供队列服务,官方推荐使用 RabbitMQ 和 Redis 等。

    • 任务执行单元 Worker

    Worker 是执行任务的处理单元,它实时监控消息队列,获取队列中调度的任务,并执行它。

    • 任务结果存储 Backend

    Backend 用于存储任务的执行结果,以供查询。同消息中间件一样,存储也可使用 RabbitMQ, Redis 和 MongoDB 等。

    • 使用 Celery 实现异步任务的步骤:

    (1) 创建一个 Celery 实例
    (2) 启动 Celery Worker ,通过delay()apply_async()(delay 方法封装了 apply_async, apply_async支持更多的参数 ) 将任务发布到broker
    (3) 应用程序调用异步任务

    (4)存储结果 (发布的任务需要return才会有结果,否则为空)

    Celery Beat:任务调度器,Beat进程会读取配置文件的内容,周期性地将配置中到期需要执行的任务发送给任务队列

    • 使用 Celery 实现定时任务的步骤:

    (1) 创建一个 Celery 实例

    (2) 配置文件中配置任务 ,发布任务 celery A xxx beat

    (3) 启动 Celery Worker

    (4) 存储结果

    celery定时任务简单使用

    以下是使用celery实现一个定时任务的demo,能够良好的定时执行。

    1. 目录结构如下
    
    shylin@shylin:~/Desktop$ tree celery_task
    celery_task
    ├── celeryconfig.py    # celeryconfig配置文件
    ├── celeryconfig.pyc
    ├── celery.py   # celery对象
    ├── celery.pyc
    ├── epp_scripts   # 任务函数
    │   ├── __init__.py
    │   ├── __init__.pyc
    │   ├── test1.py
    │   ├── test1.pyc
    │   ├── test2.py
    │   └── test2.pyc
    ├── __init__.py
    └── __init__.pyc
    
    1. celery配置文件 celeryconfig.py
    from __future__ import absolute_import # 拒绝隐式引入,因为celery.py的名字和celery的包名冲突,需要使用这条语句让程序正确地运行
    from celery.schedules import crontab
    
    broker_url = "redis://127.0.0.1:6379/5"  
    result_backend = "redis://127.0.0.1:6379/6"
    
    broker_url = "redis://127.0.0.1:6379/2"   # 使用redis存储任务队列
    result_backend = "redis://127.0.0.1:6379/6"  # 使用redis存储结果
    
    task_serializer = 'json'
    result_serializer = 'json'
    accept_content = ['json']
    timezone = "Asia/Shanghai"  # 时区设置
    worker_hijack_root_logger = False  # celery默认开启自己的日志,可关闭自定义日志,不关闭自定义日志输出为空
    result_expires = 60 * 60 * 24  # 存储结果过期时间(默认1天)
    
    # 导入任务所在文件
    imports = [
        "celery_task.epp_scripts.test1",  # 导入py文件
        "celery_task.epp_scripts.test2",
    ]
    
    
    # 需要执行任务的配置
    beat_schedule = {
        "test1": {
            "task": "celery_task.epp_scripts.test1.celery_run",  #执行的函数
            "schedule": crontab(minute="*/1"),   # every minute 每分钟执行 
            "args": ()  # # 任务函数参数
        },
    
        "test2": {
            "task": "celery_task.epp_scripts.test2.celery_run",
            "schedule": crontab(minute=0, hour="*/1"),   # every minute 每小时执行
            "args": ()
        },
    
    }
    
    "schedule": crontab()与crontab的语法基本一致
    "schedule": crontab(minute="*/10",  # 每十分钟执行
    "schedule": crontab(minute="*/1"),   # 每分钟执行
    "schedule": crontab(minute=0, hour="*/1"),    # 每小时执行
    1. celery初始化文件
    # coding:utf-8
    from __future__ import absolute_import # 拒绝隐式引入,因为celery.py的名字和celery的包名冲突,需要使用这条语句让程序正确地运行
    from celery import Celery
    
    # 创建celery应用对象
    app = Celery("celery_demo")
    
    # 导入celery的配置信息
    app.config_from_object("celery_task.celeryconfig")
    
    
    1. 任务函数(epp_scripts目录下)
    # test1.py
    from celery_task.celery import app
    
    def test11():
        print("test11----------------")
    
    def test22():
        print("test22--------------")
        test11()
    
    @app.task
    def celery_run():
        test11()
        test22()
    
    if __name__ == '__main__':
        celery_run()
    ------------------------------------------------------------
    # test2.py
    from celery_task.celery import app
    
    def test33():
        print("test33----------------")
        # print("------"*50)
    
    def test44():
        print("test44--------------")
        # print("------" * 50)
        test33()
    
    @app.task
    def celery_run():
        test33()
        test44()
    
    
    if __name__ == '__main__':
        celery_run()
    
    1. 发布任务
    # 在celery_task同级目录下执行
    shylin@shylin:~/Desktop$ celery -A celery_task beat
    celery beat v4.2.0 (windowlicker) is starting.
    __    -    ... __   -        _
    LocalTime -> 2018-06-29 09:42:02
    Configuration ->
        . broker -> redis://127.0.0.1:6379/5
        . loader -> celery.loaders.app.AppLoader
        . scheduler -> celery.beat.PersistentScheduler
        . db -> celerybeat-schedule
        . logfile -> [stderr]@%WARNING
        . maxinterval -> 5.00 minutes (300s)
    
    1. 执行任务
    # 在celery_task同级目录下执行
    shylin@shylin:~/Desktop$ celery -A celery_task worker --loglevel=info
    
     -------------- celery@shylin v4.2.0 (windowlicker)
    ---- **** ----- 
    --- * ***  * -- Linux-4.15.0-23-generic-x86_64-with-Ubuntu-18.04-bionic 2018-06-29 12:06:53
    -- * - **** --- 
    - ** ---------- [config]
    - ** ---------- .> app:         belletone:0x7f5b876f1a10
    - ** ---------- .> transport:   redis://127.0.0.1:6379/5
    - ** ---------- .> results:     redis://127.0.0.1:6379/6
    - *** --- * --- .> concurrency: 8 (prefork)
    -- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
    --- ***** ----- 
     -------------- [queues]
                    .> celery           exchange=celery(direct) key=celery
    
    
    [tasks]
      . celery_task.epp_scripts.test1.celery_run
      . celery_task.epp_scripts.test2.celery_run
    
    [2018-06-29 12:06:54,107: INFO/MainProcess] Connected to redis://127.0.0.1:6379/5
    [2018-06-29 12:06:54,116: INFO/MainProcess] mingle: searching for neighbors
    [2018-06-29 12:06:55,143: INFO/MainProcess] mingle: all alone
    [2018-06-29 12:06:55,161: INFO/MainProcess] celery@shylin ready.
    [2018-06-29 12:07:00,073: INFO/MainProcess] Received task: celery_task.epp_scripts.test2.celery_run[f4522425-b744-4f1a-8c6c-eb37ab99842b]  
    [2018-06-29 12:07:00,075: INFO/MainProcess] Received task: celery_task.epp_scripts.test1.celery_run[3e00aa9c-0947-49b9-8ee4-cc75d6dc37ab]  
    [2018-06-29 12:07:00,078: WARNING/ForkPoolWorker-6] test33----------------
    [2018-06-29 12:07:00,079: WARNING/ForkPoolWorker-6] test44--------------
    [2018-06-29 12:07:00,079: WARNING/ForkPoolWorker-6] test33----------------
    [2018-06-29 12:07:00,079: WARNING/ForkPoolWorker-4] test11----------------
    [2018-06-29 12:07:00,081: WARNING/ForkPoolWorker-4] test22--------------
    [2018-06-29 12:07:00,081: WARNING/ForkPoolWorker-4] test11----------------
    [2018-06-29 12:07:00,094: INFO/ForkPoolWorker-6] Task celery_task.epp_scripts.test2.celery_run[f4522425-b744-4f1a-8c6c-eb37ab99842b] succeeded in 0.0169868329995s: None
    [2018-06-29 12:07:00,094: INFO/ForkPoolWorker-4] Task celery_task.epp_scripts.test1.celery_run[3e00aa9c-0947-49b9-8ee4-cc75d6dc37ab] succeeded in 0.0161407030009s: None
    

    celery相关命令

    # 在celery_task同级目录下执行   celery worker/beat xxx
    celery -A celery_task beat  # 发布任务
    celery -A celery_task worker --loglevel=info  # 执行任务
    celery -B -A celery_task worker --loglevel=info  # 合并成一条
    
    /home/shylin/.virtualenvs/belle/bin/celery -B -A /home/shylin/Desktop/sky_server worker --loglevel=info
    
    
    command= /usr/local/thirdparty/sky_server_env/bin/celery  -B -A celery_task worker
    directory=/usr/local/cloud   # celery_task work不确定是否可行?
    # 注意修改broker路径
    # celery_task放在 /usr/local/cloud/
    python -m celeryconfig # 检查配置文件
    
    nohup /usr/local/thirdparty/sky_server_env/bin/celery  -B -A celery_task worker -l info --workdir=/usr/local/cloud/ &     # 启动命令

    定时方式

    from celery.schedules import crontab
    from datetime import timedelta
    ......
    
    方式一:
     "schedule": timedelta(seconds=30), # hours=xx,minutes=xx 每小时/每分钟  (此项可以精确到秒)
    
    方式二:
     "schedule": crontab(minute="*/10"),   # every 10 minutes  
    # 后台启动 celery worker进程 
    celery multi start work_1 -A appcelery  
    # work_1 为woker的名称,可以用来进行对该进程进行管理
    
    # 多进程相关
    celery multi stop WOERNAME      # 停止worker进程,有的时候这样无法停止进程,就需要加上-A 项目名,才可以删掉
    celery multi restart WORKNAME        # 重启worker进程
    
    # 查看进程数
    celery status -A celery_task       # 查看该项目运行的进程数   celery_task同级目录下
    
    执行完毕后会在当前目录下产生一个二进制文件,celerybeat-schedule 。
    该文件用于存放上次执行结果:
      1、如果存在celerybeat-schedule文件,那么读取后根据上一次执行的时间,继续执行。
      2、如果不存在celerybeat-schedule文件,那么会立即执行一次。
      3、如果存在celerybeat-schedule文件,读取后,发现间隔时间已过,那么会立即执行。
    

    Shylin

    展开全文
  • windows7当任务栏图标无法添加时使用时,使用该文件可以把桌面图标移到任务
  • android Activity任务使用总结

    千次阅读 2020-08-01 14:33:53
    前言 android上对于任务栈的控制还是比较常见的,尤其是在小程序、小游戏的场景。 笔者近期也有在实际项目中碰到,因此就好好学习了一下,作...android上要使用任务栈,除了要了解启动模式之外,就是需要了解taskAffi

    前言

    android上对于任务栈的控制还是比较常见的,尤其是在小程序、小游戏的场景。
    笔者近期也有在实际项目中碰到,因此就好好学习了一下,作此文以记录。
    本文主要还是自己的一些使用总结,如有不对或者需要补充的地方,欢迎评论交流。

    此文需要有对android启动模式的基础,还不了解的读者推荐看下笔者前面的文章:
    完全理解android Activity启动模式LauchMode (深入Activity与任务栈)

    使用概念

    android上要使用多任务栈,除了要了解启动模式之外,就是需要了解taskAffinity这个属性。

    关于taskAffinity的官网地址:
    https://developer.android.com/guide/topics/manifest/activity-element#aff

    使用taskAffinity属性大概有以下几种场景:

    1. 当前的taskAffinity与启动的taskAffinity相同。
      这种情况下,无论什么情况都会启动在同一个任务栈中。这也是默认的情况。
    2. 当前的taskAffinity与启动的taskAffinity不同。
      这种情况下,如果有FLAG_ACTIVITY_NEW_TASK的flag,那么会在新的任务栈中启动activity。如果没有设置这个flag,只要是启动模式中singleTask和singleInstance,那么也会在新的任务栈中启动activity。
    3. 启动的taskAffinity为空。
      为空代表无论当前的activity是哪个任务栈,启动的activity都默认与其任务栈不相同。如果是带有FLAG_ACTIVITY_NEW_TASK的flag,或者启动模式为singleTask或singleInstance,那么肯定会启动一个新的任务栈。

    启动模式对多个实例的支持

    • 支持多个实例:standard和singleTop
    • 不支持多个实例:singleTask和singleInstance

    默认一般都是支持多个实例的,主要讲下不支持多个实例的场景:

    1. 逻辑非常独立,但是入口较多的页面。如小程序、小游戏。
    2. 需要使用到全局单例,全局不适合有多个的页面。如语音,视频。

    singleInstance最好要是单独的任务栈名称

    假设主页面是A,B的启动模式是singleInstance并且任务栈名称与A相同。
    那么按照如下操作,会有不合理的场景出现:

    1. 首页启动A
    2. A启动B
    3. 回到首页再启动A

    此时由于B是singleInstance,因此B不会在A的任务栈中。而又由于B是默认的任务栈名称,因此也没有自己单独的任务栈。
    于是此时B虽然是存活的状态,但是却无法通过操作系统上的操作回到B。换句话说对用户来说B就是不可见的了。

    为了避免这种情况的发生,除了给singleInstance设置单独的任务栈名称之外。也可以通过其他的一些方式,比如:

    1. 设置悬浮窗给用户保留进入B的入口。(这个需要权限)
    2. 设置单独的桌面图标可以直接跳转到B。

    任务栈是否需要主要关闭

    如果不主动关闭任务栈,那么用户还是可以再系统的任务栈预览页面重新进入的。
    笔者还是列举了自己使用时碰到的两种常见:

    1. 不需要主动关闭。
      比如这个页面是小程序,我们期望用户第二次进入的时候要更快一点。那么在这种情况下,不仅不能关闭,而且最好关闭不要使用finish,而使用moveToBack。
    2. 主动关闭。
      参数存在过期,或者不可用重复参数多次进入的页面。比如一些对战游戏会有房间的概念,在对战结束之后房间就没有了。这时候以过期的房间号进入页面是没有意义的,因此需要把任务栈主动关闭,避免用户主动操作触发这个错误的逻辑。

    Demo

    笔者自己写了demo用于测试多任务栈下的各种场景,如有需要可以自行查看。

    Demo github地址:https://github.com/Double2hao/ActivityTaskTest

    展开全文
  • SpringBoot定时任务使用详解

    千次阅读 2019-12-19 03:50:27
    在进行SpringBoot的定时任务使用介绍之前,我觉得有必要向大家说明一下实现定时任务的几种方式。 如果你不想了解其他方式,可跳过第一节。 一、定时任务的几种实现方式 在JAVA开发领域,目前可以通过以下几种...

    在进行SpringBoot的定时任务使用介绍之前,我觉得有必要向大家说明一下实现定时任务的几种方式。

    如果你不想了解其他方式,可跳过第一节。

     一、定时任务的几种实现方式

    在JAVA开发领域,目前可以通过以下几种方式进行定时任务:

    (注:因为这篇文章主要介绍在SpringBoot中使用定时任务,所以其他实现方式这里只做简单记录,有兴趣的可以去深入了解)

    1、Timer:jdk中自带的一个定时调度类,可以简单的实现按某一频度进行任务执行。提供的功能比较单一,无法实现复杂的调度任务。

    2、ScheduledExecutorService:也是jdk自带的一个基于线程池设计的定时任务类。其每个调度任务都会分配到线程池中的一个线程执行,所以其任务是并发执行的,互不影响。

    3、Spring Task:Spring提供的一个任务调度工具,支持注解和配置文件形式,支持Cron表达式,使用简单且功能强大。

    4、Quartz:一款功能强大的任务调度器,可以实现较为复杂的调度功能,如每月一号执行、每天凌晨执行、每周五执行等等,还支持分布式调度,就是配置稍显复杂。

     

    二、SpringBoot中定时任务使用

    1、引入依赖

    只需要引入spring-boot-starter依赖就可以。

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

    2、 开启定时任务

    在启动类上面加上@EnableScheduling注解即可开启定时任务。

    @SpringBootApplication
    @EnableScheduling
    public class TaskApplication {
        public static void main(String[] args) {
            SpringApplication.run(TaskApplication.class);
        }
    }

    3、创建定时任务类

    创建一个定时任务类,在方法上加上@Scheduled注解,注解的参数可以配置时间。注意不要忘记加上@Component。

    @Component
    public class MyTask {
        @Scheduled(fixedRate = 5000)
        public void testTaskFirst() {
            System.out.println("定时任务一:每五秒执行一次,当前时间:"+ LocalTime.now());
        }
    
        @Scheduled(cron = "0 28 03 ? * *")
        public void testTaskSecond() {
            System.out.println("定时任务二:指定每天3:26执行,当前时间:"+LocalTime.now());
        }
    }

    测试结果:

    我们可以清楚的看到两个定时任务分别都已经执行。

     

    三、@Scheduled注解参数说明

    1、参数说明:

    @Scheduled 参数可以接受两种定时的设置,一种是我们常用的cron="*/5 * * * * ?",一种是 fixedRate = 5000,两种都表示每隔五秒打印一下内容。

    fixedRate 说明:

    • @Scheduled(fixedRate = 5000) :上一次开始执行时间点之后5秒再执行。
    • @Scheduled(fixedDelay = 5000) :上一次执行完毕时间点之后5秒再执行。
    • @Scheduled(initialDelay=1000, fixedRate=5000) :第一次延迟1秒后执行,之后按fixedRate的规则每5秒执行一次。

     

     四、Cron表达式与生成工具

     Cron表达式生成工具地址:http://qqe2.com/cron

     

    展开全文
  • @KafkaListener() 与计划任务同时使用

    千次阅读 2019-06-04 09:34:45
    @KafkaListener 与计划任务同时使用前言计划任务周期执行延迟时间总结 前言 我们在开发过程中经常会用到计划任务,而计划任务中我们...这样就会导致我们使用注解方式的计划任务无法生效,如果这个时候我们仍然需要使...
  • 无法使用任务管理器的解决方法

    千次阅读 2009-02-02 21:06:00
    无法使用任务管理器的解决方法 1.检查 c:/windows/system32 或 c:/winnt/system32 下是否有名为taskmgr.exe的文件如果没有,请从其它使用同一版本Windows的电脑中复制一个过来 2.用 c:/w
  • win7下计划任务schtasks使用详解及"错误:无法加载列资源"的解决方法 schtasks 命令简述: 安排命令和程序,使其定期运行或在指定时间运行。向计划中添加任务和从中删除任务、根据需要启动和停止任务以及显示和...
  • 使用Gradle自定义任务task

    千次阅读 2018-10-16 11:27:50
    任务是 Gradle 构建中的两个基本概念之一,而任务的定义和使用有多种形式,以下就给大家介绍几个task 的定义和使用。 定义任务基本语法 // 使用task 后带任务名称 加上执行闭包{} task t1 { println 't1' } // ...
  • tp5使用workerman实现异步任务

    万次阅读 2019-08-20 10:58:13
    采集数据时过程很慢,导致无法继续进行其他任务,,避免主业务被长时间阻塞,故而将其提交给异步任务,当任务完成通知客户端即可 流程 前端业务: 由于本系统采用iframe结构,为避免点击其他页面业务中断,所以...
  • 使用Quartz处理定时任务

    千次阅读 2013-12-19 09:36:50
    通常开发中提到定时任务,大多是说异步定期执行的批处理任务,比如夜里低峰时段的备份、统计,或者是每周、每...如果只有少量的定时任务使用系统的crontab就足够了,这也是90%情况下的首选方案。但是当任务数量
  • debian 中定时任务cron使用

    万次阅读 2015-10-19 17:52:37
    在linux下有两种方法来让一个命令或者脚本执行: ...每行都含有要指定的任务的命令、参数与选项,以及要执行任务的时间。(cron 软件在后台运行并且经常检查 /etc/crontab 文件。cron 软件也检查 /var/
  • linux下定时任务crontab的使用详解

    千次阅读 2018-02-23 13:14:40
    前一天学习了 at 命令是针对仅运行一次的任务,循环运行的...另外, 由于使用者自己也可以设置计划任务,所以, Linux 系统也提供了使用者控制计划任务的命令 :crontab 命令。一、crond简介crond是linux下用来...
  • Django 使用定时任务的多种姿势对比

    千次阅读 2020-05-17 18:44:51
    因为django-apscheduler会创建表来存储定时任务的一些信息,所以将app加入之后需要迁移数据 python manage.py migrate 4、完整示例 在views.py中增加你的定时任务代码 注意:如果在其他文件中添加代码是没有效果
  • easyswoole-异步任务使用注意

    千次阅读 2019-06-18 18:26:25
    异步任务对于优化业务实现提高响应效率很有帮助。 http://easyswoole.com/Manual/2.x/Cn/_book/Advanced/async_task.html 投递闭包 use EasySwoole\Core\Swoole\Task\TaskManager; TaskManager::async(function ()...
  • 需求是做定时任务推送消息或者修改状态,springBoot中在多线程中为了线程安全,一般都是防止注解注入的,新线程中@Autowired注解无法注入需要的bean(即:保存历史数据的service层),程序一直在报 ...
  • 需求:app程序进入后台或者手机屏幕关闭,开启的定时器任务使用timers的计数任务)继续执行问题:调试手机usb连接电脑,程序进入后台或手机屏幕关闭,开启的定时器任务正常执行;但是,如果拔掉usb数据线,定时器...
  • win7下计划任务schtasks使用详解及"错误:无法加载列资源"的解决方法 schtasks 命令简述: 安排命令和程序,使其定期运行或在指定时间运行。向计划中添加任务和从中删除任务、根据需要启动和停止任务以及显示...
  • QTaskManager是一个对抽象任务进行调度、分配及管理的简化管理框架,支持并行执行任务、顺序执行任务、按时执行任务、串行执行任务等基本任务操作。本文是对框架使用方式的介绍。
  • 顾名思义就是线程的池子,里面有若干线程,它们的任务就是执行提交给线程池的任务,执行完之后不会退出,而是继续等待或执行新任务。 线程池由两部分组成:任务队列和工作线程。 任务队列:保存待执行的任务; ...
  • 我们怎样才能在服务器上使用asp.net定时执行任务而不需要安装windows service?我们经常需要运行一些维护性的任务或者像发送提醒邮件给用户这样的定时任务。这些仅仅通过使用Windows Service就可以完成。Asp.net通常...
  • 因业务需要,经常会遇到主线程中包含其他关联业务,然...一、Springboot 使用异步任务 1、SpringBootApplication启动类添加@EnableAsync注解; 2、@Async使用 (1)类或者方法中使用@Async注解,类上标有该注...
  •  本文是我在一个技术分享群里面,对于任务调度和开源软件opencron的分享和使用体会,现在整理成文字,供大家参考。  大家好,下面我来分享一下 部署和使用 opencron 任务调度工具的一些经验和体会  我计划...
  • 使用ExecutorService,解决多任务同时进行,并等待全部任务完成合并数据一、ExecutorService使用二、Future使用三、功能实现AAAThreadHttpRequestCallable方法结论 一、ExecutorService使用 刚好做项目的时候碰到...
  • 由于我经常会使用win10搜索框进行定时等操作,最近发现搜索用不了了,通过谷歌得知可能需要重新安装下小娜: 首先按下win+R命令,输入cmd即可进入命令提示符模式,然后输入 start powershell 随后在弹出的界面中...
  • 使用Crontab定时执行Spark任务

    千次阅读 2017-03-15 16:54:40
    今天的主要内容有: Linux下使用定时器crontab ... 实例:每天0点30分执行Spark任务 1. Linux下使用定时器crontab1、安装yum -y install vixie-cron yum -y install crontabs2、启停命令service crond start
  • 关于gulp中使用del,使用del删除文件夹后再执行任务可以,但是执行完任务后去删除一个文件夹,就删除不了关于gulp中使用del,使用del删除文件夹后再执行任务可以,但是执行完任务后去删除一个文件夹,就删除不了
  • 使用xml配置Quartz,实现定时任务

    千次阅读 2017-12-12 11:00:21
    使用xml配置Quartz,实现定时任务使用xml配置前景以前我是使用java代码配置Quartz任务的,到最好你会发现,这个类使用其他类成员变量会无法自动注入问题 始终是空指针问题,到最后只能手动到SpingContext中去取,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 866,173
精华内容 346,469
关键字:

任务无法使用