简单东西 Java 定时调度线程池用法

    xiaoxiao2021-03-25  80

    If any execution of the task encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via cancellation or termination of the executor. If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.

    Java 的 ScheduledExecutorService,定时调度器,可以实现按一定周期执行某个任务的功能,它的 scheduleAtFixedRate 方法,定期执行某个任务,当任务执行时间过长,超过它的周期时,如果当前任务没有执行完成,是不会开始下一次的任务的。 这有一个好处就是,可以预防任务堆积导致工作线程都被占满的情况。

    public class AddedUpJob implements Runnable{ /* (non-Javadoc) * @see java.lang.Runnable#run() */ @Override public void run() { System.out.println(Thread.currentThread().getName()+new Date()); try { Thread.sleep(300000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("after 5 minute ,end up the job."); } } public static void main(String[] args) { ScheduledExecutorService executor = Executors.newScheduledThreadPool(3); AddedUpJob job = new AddedUpJob(); executor.scheduleAtFixedRate(job, 1, 5, TimeUnit.SECONDS); }

    验证一下,如果工作任务休眠一段时间,超过了定时的周期,那么下一轮定时任务会等待该任务执行完成后才开始。 这点跟 Quartz 的定时调度方法不一样,Quartz 会按照调度周期,执行相应的定时任务,任务之间都是独立的,所以可能出现任务堆积的情况。另外 Spring 集成 quartz 时,每次取到的 Shedule 对象都是同一个,说明 Quartz 的调度器类默认的是单例。

    SchedulerFactory sf1 = new StdSchedulerFactory(); Scheduler scheduler1 = sf.getScheduler(); SchedulerFactory sf2 = new StdSchedulerFactory(); Scheduler scheduler2 = sf.getScheduler(); System.out.println(scheduler1 ==scheduler2);

    输出结果为 true。当初选用 Quartz 作为定时任务的调度工具,是因为它强大可配置的Cron 表达式,但是对于频繁执行的、而且执行时间较长的任务来说,很容易将 Quartz的工作线程耗尽,从而影响其他任务的正常执行。所以只能分开处理了。

    延伸扩展

    碰到过这样一种编码场景:线程池工作线程数固定 2,提交了三个任务,每个任务都是 while(true) 循环处理 Redis 消息监听,结果导致第三个任务无法得到工作线程,任务永远都没有被启动。多线程调度时,应当对工作线程数以及提交的任务的处理过程充分了解,避免这种问题。

    转载请注明原文地址: https://ju.6miu.com/read-23793.html

    最新回复(0)