线程执行者(七)执行者延迟运行一个任务

简介:

执行者延迟运行一个任务

执行者框架提供ThreadPoolExecutor类,使用池中的线程来执行Callable和Runnable任务,这样可以避免所有线程的创建操作。当你提交一个任务给执行者,会根据执行者的配置尽快执行它。在有些使用情况下,当你对尽快执行任务不感觉兴趣。你可能想要在一段时间之后执行任务或周期性地执行任务。基于这些目的,执行者框架提供 ScheduledThreadPoolExecutor类。

在这个指南中,你将学习如何创建ScheduledThreadPoolExecutor和如何使用它安排任务在指定的时间后执行。

准备工作…

这个指南的例子使用Eclipse IDE实现。如果你使用Eclipse或其他IDE,如NetBeans,打开它并创建一个新的Java项目。

如何做…

按以下步骤来实现的这个例子:

1.创建Task类,实现Callable接口,参数化为String类型。


1 public class Task implements Callable<String> {

2.声明一个私有的、类型为String、名为name的属性,用来存储任务的名称。


1 private String name;

3.实现Task类的构造器,初始化name属性。


1 public Task(String name) {
2 this.name=name;
3 }

4.实现call()方法,写入实际日期到控制台,返回一个文本,如:Hello, world。


1 public String call() throws Exception {
2 System.out.printf("%s: Starting at : %s\n",name,new Date());
3 return "Hello, world";
4 }

5.实现示例的主类,创建Main类,实现main()方法。


1 public class Main {
2 public static void main(String[] args) {

6.使用Executors类的newScheduledThreadPool()方法,创建ScheduledThreadPoolExecutor类的一个执行者。传入参数1。


1 ScheduledThreadPoolExecutor executor=(ScheduledThreadPoolExecutor)Executors.newScheduledThreadPool(1);

7.使用ScheduledThreadPoolExecutor实例的schedule()方法,初始化和开始一些任务(本例中5个任务)。


1 System.out.printf("Main: Starting at: %s\n",new Date());
2 for (int i=0; i<5; i++) {
3 Task task=new Task("Task "+i);
4 executor.schedule(task,i+1 , TimeUnit.SECONDS);
5 }

8.使用shutdown()方法关闭执行者。


1 executor.shutdown();

9.使用执行者的awaitTermination()方法,等待所有任务完成。


1 try {
2 executor.awaitTermination(1, TimeUnit.DAYS);
3 } catch (InterruptedException e) {
4 e.printStackTrace();
5 }

10.写入一条信息表明程序结束时间。


1 System.out.printf("Main: Ends at: %s\n",new Date());

它是如何工作的…

在这个示例中,关键的一点是Main类和ScheduledThreadPoolExecutor的管理。正如使用ThreadPoolExecutor类创建预定的执行者,Java建议利用Executors类。在本例中,你使用newScheduledThreadPool()方法。你用1作为参数传给这个方法。这个参数是你想要让线程池创建的线程数。

你必须使用schedule()方法,让执行者在一段时间后执行任务。这个方法接收3个参数,如下:

  • 你想要执行的任务
  • 你想要让任务在执行前等待多长时间
  • 时间单位,指定为TimeUnit类的常数

在本例中,每个任务等待的秒数(TimeUnit.SECONDS)等于它在任务数组中的位置再加1。

注意事项:如果你想在给定时间执行一个任务,计算这个日期与当前日期的差异,使用这个差异作为任务的延迟。

以下截图显示这个示例执行的输出:

5

你可以看出这些任务是如何开始执行的,一秒执行一个。所有任务都是同时提交给执行者的,但每个任务比之前的任务都有1秒的延迟。

不止这些…

你也可以使用Runnable接口实现任务,因为ScheduledThreadPoolExecutor类的schedule()方法接收这两种类型(Runnable和Callable)的任务。

尽管ScheduledThreadPoolExecutor类是ThreadPoolExecutor类的子类,因此,它继承 ThreadPoolExecutor类的所有功能,但Java建议使用ScheduledThreadPoolExecutor仅适用于调度任务。

最后,你可以配置ScheduledThreadPoolExecutor的行为,当你调用shutdown()方法时,并且有待处理的任务正在等待它们延迟结束。默认的行为是,不管执行者是否结束这些任务都将被执行。你可以使用ScheduledThreadPoolExecutor类的setExecuteExistingDelayedTasksAfterShutdownPolicy()方法来改变这种行为。使用false,调用 shutdown()时,待处理的任务不会被执行。

参见

  • 在第4章,线程执行者中的执行者执行返回结果的任务指南
目录
相关文章
|
3月前
|
存储 Java 数据库
如何处理线程池关闭时未完成的任务?
总之,处理线程池关闭时未完成的任务需要综合考虑多种因素,并根据实际情况选择合适的处理方式。通过合理的处理,可以最大程度地减少任务丢失和数据不一致等问题,确保系统的稳定运行和业务的顺利开展。
173 64
|
1月前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
109 17
|
3月前
|
消息中间件 监控 Java
线程池关闭时未完成的任务如何保证数据的一致性?
保证线程池关闭时未完成任务的数据一致性需要综合运用多种方法和机制。通过备份与恢复、事务管理、任务状态记录与恢复、数据同步与协调、错误处理与补偿、监控与预警等手段的结合,以及结合具体业务场景进行分析和制定策略,能够最大程度地确保数据的一致性,保障系统的稳定运行和业务的顺利开展。同时,不断地优化和改进这些方法和机制,也是提高系统性能和可靠性的重要途径。
143 62
|
6月前
|
编解码 网络协议 API
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
|
3月前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
76 12
|
4月前
|
缓存 负载均衡 Java
c++写高性能的任务流线程池(万字详解!)
本文介绍了一种高性能的任务流线程池设计,涵盖多种优化机制。首先介绍了Work Steal机制,通过任务偷窃提高资源利用率。接着讨论了优先级任务,使不同优先级的任务得到合理调度。然后提出了缓存机制,通过环形缓存队列提升程序负载能力。Local Thread机制则通过预先创建线程减少创建和销毁线程的开销。Lock Free机制进一步减少了锁的竞争。容量动态调整机制根据任务负载动态调整线程数量。批量处理机制提高了任务处理效率。此外,还介绍了负载均衡、避免等待、预测优化、减少复制等策略。最后,任务组的设计便于管理和复用多任务。整体设计旨在提升线程池的性能和稳定性。
120 5
|
5月前
|
Java Spring
运行@Async注解的方法的线程池
自定义@Async注解线程池
210 3
|
6月前
|
前端开发 JavaScript 大数据
React与Web Workers:开启前端多线程时代的钥匙——深入探索计算密集型任务的优化策略与最佳实践
【8月更文挑战第31天】随着Web应用复杂性的提升,单线程JavaScript已难以胜任高计算量任务。Web Workers通过多线程编程解决了这一问题,使耗时任务独立运行而不阻塞主线程。结合React的组件化与虚拟DOM优势,可将大数据处理等任务交由Web Workers完成,确保UI流畅。最佳实践包括定义清晰接口、加强错误处理及合理评估任务特性。这一结合不仅提升了用户体验,更为前端开发带来多线程时代的全新可能。
156 1
|
6月前
|
存储 监控 Java
|
6月前
|
消息中间件 设计模式 安全
多线程魔法:揭秘一个JVM中如何同时运行多个消费者
【8月更文挑战第22天】在Java虚拟机(JVM)中探索多消费者模式,此模式解耦生产与消费过程,提升系统性能。通过`ExecutorService`和`BlockingQueue`构建含2个生产者及4个消费者的系统,实现实时消息处理。多消费者模式虽增强处理能力,但也引入线程安全与资源竞争等挑战,需谨慎设计以确保高效稳定运行。
112 2

热门文章

最新文章

相关实验场景

更多