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

简介: 声明:本文是《 Java 7 Concurrency Cookbook 》的第四章,作者: Javier Fernández González     译者:许巧辉     校对:方腾飞,叶磊 执行者延迟运行一个任务 执行者框架提供ThreadPoolExecutor类,使用池中的线程来执行Callable和Runnable任务,这样可以避免所有线程的创建操作。

声明:本文是《 Java 7 Concurrency Cookbook 》的第四章,作者: Javier Fernández González 译者:许巧辉 校对:方腾飞,叶磊

执行者延迟运行一个任务

执行者框架提供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()时,待处理的任务不会被执行。

参见

目录
相关文章
|
18天前
|
缓存 Java 调度
Java并发编程:深入解析线程池与Future任务
【7月更文挑战第9天】线程池和Future任务是Java并发编程中非常重要的概念。线程池通过重用线程减少了线程创建和销毁的开销,提高了资源利用率。而Future接口则提供了检查异步任务状态和获取任务结果的能力,使得异步编程更加灵活和强大。掌握这些概念,将有助于我们编写出更高效、更可靠的并发程序。
|
5天前
|
Java Linux
1:1线程模型对于I/O密集型任务有什么问题
1:1线程模型对于I/O密集型任务有什么问题?
|
16天前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
33 1
|
22天前
|
安全 开发者
LabVIEW程序退出后线程仍在运行问题
LabVIEW程序退出后线程仍在运行问题
21 2
|
1月前
|
Java
java线程池执行任务(一次任务、固定间隔时间任务等)
java线程池执行任务(一次任务、固定间隔时间任务等)
17 1
|
29天前
|
存储 测试技术
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
32 0
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
|
1月前
|
Java 程序员
Java多线程编程是指在一个进程中创建并运行多个线程,每个线程执行不同的任务,并行地工作,以达到提高效率的目的
【6月更文挑战第18天】Java多线程提升效率,通过synchronized关键字、Lock接口和原子变量实现同步互斥。synchronized控制共享资源访问,基于对象内置锁。Lock接口提供更灵活的锁管理,需手动解锁。原子变量类(如AtomicInteger)支持无锁的原子操作,减少性能影响。
34 3
|
1月前
|
Java
【技术解码】Java线程的五味人生:新建、就绪、运行、阻塞与死亡的哲学解读!
【6月更文挑战第19天】Java线程生命周期如同人生旅程,经历新建、就绪、运行、阻塞至死亡五阶段。从`new Thread()`的诞生到`start()`的蓄势待发,再到`run()`的全力以赴,线程在代码中奔跑。阻塞时面临挑战,等待资源释放,最终通过`join()`或中断结束生命。线程的每个状态转变,都是编程世界与哲思的交汇点。
|
16天前
|
设计模式 安全 Java
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
16 0
|
16天前
|
设计模式 SQL 安全
Java面试题:设计一个线程安全的内存管理器,使用观察者模式来通知所有线程内存使用情况的变化。如何确保在添加和移除内存块时的线程安全?如何确保任务的顺序执行和调度器的线程安全?
Java面试题:设计一个线程安全的内存管理器,使用观察者模式来通知所有线程内存使用情况的变化。如何确保在添加和移除内存块时的线程安全?如何确保任务的顺序执行和调度器的线程安全?
15 0

相关实验场景

更多