任务调度线程池 小灰灰 2023-10-12 19:59 18阅读 0赞 **目录** Timer ScheduledExecutorService 正确处理执行任务异常 -------------------- ###### Timer ###### 在『任务调度线程池』功能加入之前,可以使用 java.util.Timer 来实现定时功能,Timer 的优点在于简单易用,但 由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个 任务的延迟或异常都将会影响到之后的任务。 public class Test { public static void main(String[] args) { Timer timer = new Timer(); TimerTask task1 = new TimerTask() { @Override public void run() { log.debug("task 1"); sleep(2); } }; TimerTask task2 = new TimerTask() { @Override public void run() { log.debug("task 2"); } }; // 使用 timer 添加两个任务,希望它们都在 1s 后执行 // 但由于 timer 内只有一个线程来顺序执行队列中的任务, //因此『任务1』的延时,影响了『任务2』的执行 timer.schedule(task1, 1000); timer.schedule(task2, 1000); } } 输出 > 20:46:09.444 c.TestTimer \[main\] - start... > > 20:46:10.447 c.TestTimer \[Timer-0\] - task 1 > > 20:46:12.448 c.TestTimer \[Timer-0\] - task 2 ###### ScheduledExecutorService ###### **线程池支持定时以及周期性执行任务,创建一个corePoolSize为传入参数,最大线程数为整形的最大数的线程池** public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } ScheduledThreadPoolExecutor类的构造: public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue()); } ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); // 添加两个任务,希望它们都在 1s 后执行 executor.schedule(() -> { System.out.println("任务1,执行时间:" + new Date()); try { Thread.sleep(2000); } catch (InterruptedException e) { } }, 1000, TimeUnit.MILLISECONDS); executor.schedule(() -> { System.out.println("任务2,执行时间:" + new Date()); }, 1000, TimeUnit.MILLISECONDS); **输出** > 任务2,执行时间:Fri Jun 23 18:04:46 CST 2023 > 任务1,执行时间:Fri Jun 23 18:04:46 CST 2023 **scheduleAtFixedRate 例子:** **构造方法** public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); > 提交一个定期操作,该操作在给定的初始延迟后首先启用,随后在给定的时间段内启用;也就是说,执行将在 之后开始initialDelay,然后 、 initialDelay + 2 \* period然后 initialDelay + period,依此类推。 ScheduledExecutorService pool = Executors.newScheduledThreadPool(1); log.debug("start..."); pool.scheduleAtFixedRate(() -> { log.debug("running..."); }, 1, 1, TimeUnit.SECONDS); **输出** > 21:45:43.167 c.TestTimer \[main\] - start... > > 21:45:44.215 c.TestTimer \[pool-1-thread-1\] - running... > > 21:45:45.215 c.TestTimer \[pool-1-thread-1\] - running... > > 21:45:46.215 c.TestTimer \[pool-1-thread-1\] - running... > > 21:45:47.215 c.TestTimer \[pool-1-thread-1\] - running... **scheduleAtFixedRate 例子(任务执行时间超过了间隔时间):** ScheduledExecutorService pool = Executors.newScheduledThreadPool(1); log.debug("start..."); pool.scheduleAtFixedRate(() -> { log.debug("running..."); sleep(2); }, 1, 1, TimeUnit.SECONDS); 输出分析:一开始,延时 1s,接下来,由于任务执行时间 > 间隔时间,间隔被『撑』到了 2s > 21:44:30.311 c.TestTimer \[main\] - start... > > 21:44:31.360 c.TestTimer \[pool-1-thread-1\] - running... > > 21:44:33.361 c.TestTimer \[pool-1-thread-1\] - running... > > 21:44:35.362 c.TestTimer \[pool-1-thread-1\] - running... > > 21:44:37.362 c.TestTimer \[pool-1-thread-1\] - running... **scheduleWithFixedDelay 例子:** ScheduledExecutorService pool = Executors.newScheduledThreadPool(1); log.debug("start..."); pool.scheduleWithFixedDelay(()-> { log.debug("running..."); sleep(2); }, 1, 1, TimeUnit.SECONDS); 输出分析:一开始,延时 1s,scheduleWithFixedDelay 的间隔是 上一个任务结束 -> 延时 -> 下一个任务开始 所 以间隔都是 3s > 21:40:55.078 c.TestTimer \[main\] - start... > > 21:40:56.140 c.TestTimer \[pool-1-thread-1\] - running... > > 21:40:59.143 c.TestTimer \[pool-1-thread-1\] - running... > > 21:41:02.145 c.TestTimer \[pool-1-thread-1\] - running... > > 21:41:05.147 c.TestTimer \[pool-1-thread-1\] - running... 评价 整个线程池表现为:线程数固定,任务数多于线程数时,会放入无界队列排队。任务执行完毕,这些线 程也不会被释放。用来执行延迟或反复执行的任务 ###### 正确处理执行任务异常 ###### **方法1:主动捉异常** ExecutorService pool = Executors.newFixedThreadPool(1); pool.submit(() -> { try { log.debug("task1"); int i = 1 / 0; } catch (Exception e) { log.error("error:", e); } }) **方法2:使用 Future** ExecutorService pool = Executors.newFixedThreadPool(1); Future<Boolean> f = pool.submit(() -> { log.debug("task1"); int i = 1 / 0; return true; }); log.debug("result:{}", f.get());
相关 理解Java中的线程池:高效任务调度实例 在Java编程中,线程池是一种常用的资源管理机制。它允许我们在应用程序运行时预先创建一组可重用的线程。 以下是一个理解线程池和其高效任务调度实例: 1. **什么是线程池* 向右看齐/ 2024年09月15日 09:48/ 0 赞/ 9 阅读
相关 Java并发编程:线程池与任务调度实例 在Java并发编程中,线程池和任务调度是两种常用的资源管理和执行策略。 1. 线程池: 线程池是一种预先创建一定数量的线程,并通过线程池来管理这些线程。使用线程池的优点包括: 小咪咪/ 2024年09月12日 08:36/ 0 赞/ 19 阅读
相关 Java并发编程:线程池与任务调度实战示例 Java并发编程中的线程池和任务调度是两种常用的多线程管理方式。下面将通过实例详细解释这两种概念。 1. **线程池(ThreadPool)**: 线程池是一种预先创建固定 快来打我*/ 2024年09月11日 01:48/ 0 赞/ 18 阅读
相关 项目难点——【3】分布式任务调度、线程池使用、视频转换 项目难点——【3】分布式任务调度、线程池使用、视频转换 > 我们有时候在处理视频文件的时候会遇到视频格式转换问题。 1 分布式任务调度 > 在项目开发中我们想要提 雨点打透心脏的1/2处/ 2024年03月26日 12:14/ 0 赞/ 19 阅读
相关 任务调度线程池 目录 Timer ScheduledExecutorService 正确处理执行任务异常 -------------------- Timer 在『任务 小灰灰/ 2023年10月12日 19:59/ 0 赞/ 19 阅读
相关 Java线程池示例:任务窃取线程池WorkStealingPool ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E3NzIz 向右看齐/ 2023年10月08日 09:28/ 0 赞/ 22 阅读
相关 线程池-callable任务 1 带回调的线程池任务 Callable接口和Runable接口最大的区别是Callable可以拥有返回值,并可以通过回调的方式获取。同时通过Future的get方法,可 约定不等于承诺〃/ 2022年07月16日 11:07/ 0 赞/ 168 阅读
相关 Java提高——JUC线程线程池和线程调度 线程池 第四种获取线程的方法:线程池,一个ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用Executors工厂方法配置 。 短命女/ 2022年05月20日 02:25/ 0 赞/ 275 阅读
相关 任务/线程池等 考虑单线程和一个任务一个线程的不足(线程创建销毁开销,对资源的竞争) Executor 异步,任务提交和执行解耦,考虑执行策略, 任务独立(不独立导致线程饥饿死锁,运行中任 Love The Way You Lie/ 2022年03月28日 06:51/ 0 赞/ 243 阅读
还没有评论,来说两句吧...