多线程Executors之周期性执行任务

本文介绍使用Java并发编程技术实现周期性任务的方法。通过《Java并发编程的艺术》一书的指导,利用ScheduledExecutorService创建周期性执行的任务,示例代码展示了如何设定任务执行间隔和首次执行时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

书籍

《Java并发编程的艺术》—方腾飞,第8章

场景说明

拉取kafka的数据,多线程把数据追加到HDFS文件里,要求每个医院每一天的数据存放在一个文件中,每个文件有一个锁,这些锁由一个Map维护。定期清理n天前的文件的锁对象(之前的文件不会再写入数据,所以这个文件的锁也没用了)。

这里简单实现周期性执行任务。

实例代码

1、任务类

package java7.thread.chapter2.test2;

import java.text.SimpleDateFormat;


public class C1 implements Runnable {


    @Override
    public void run() {
    	// 打印当前时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(format.format(System.currentTimeMillis()));
    }

}

2、测试

package java7.thread.chapter2.test2;

import java.text.SimpleDateFormat;
import java.util.concurrent.*;

public class Main {

    public static void main(String[] args) {
    	// 带调度策略的任务执行器
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(16);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("开始:"+format.format(System.currentTimeMillis()));
       
        // C1:要周期性执行的任务
        // 2L:多久后第一次执行任务
        // 5L:以后每隔多久执行一次
        // TimeUnit.SECONDS:第二个和第三个参数的时间单位
        ScheduledFuture<?> schedule = pool.scheduleAtFixedRate(new C1(), 2L, 5L, TimeUnit.SECONDS);
    }
}

运行结果

07秒开始计时,2秒后第一次执行,以后每5秒执行一次,一直执行下去。。。
sssssssssssssssssssssssssssssssssssss

### Java 中实现多线程异步执行任务 #### 使用 `Thread` 类实现异步运行 通过继承 `Thread` 类并覆写其 `run()` 方法来定义线程的任务逻辑。当调用 `start()` 方法时,JVM 将自动调用此方法,在新启动的线程上执行其中的内容。 ```java class MyTask extends Thread { @Override public void run() { System.out.println("MyTask is running on thread " + Thread.currentThread().getName()); // Simulate a time-consuming operation, such as network request or file processing. try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("MyTask has finished."); } } ``` 创建并启动上述自定义线程对象即可触发对应的异步操作[^1]。 #### 利用 `ExecutorService` 接口简化管理 相比于手动控制生命周期的方式更为推荐的做法是借助于更高层次抽象——即基于池化机制的服务接口 `ExecutorService` 来提交可执行单元给它内部维护着的一组工作进程去完成;这不仅能够有效减少资源消耗还能更好地支持并发场景下的性能优化需求。 ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TaskRunner { private static final ExecutorService executor = Executors.newFixedThreadPool(10); public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 10; ++i) { int taskId = i; executor.submit(() -> { System.out.printf("Executing task %d from pool thread %s\n", taskId, Thread.currentThread().getName()); try { Thread.sleep((long)(Math.random()*10_000)); } catch (InterruptedException ignored) {} System.out.printf("Finished executing task %d.\n", taskId); }); } // Shutdown the service after all tasks have been submitted. executor.shutdown(); // Wait until all threads are finish execution or timeout occurs. while (!executor.isTerminated()) {} System.out.println("All tasks completed."); } } ``` 这段程序展示了如何利用固定大小的工作队列来进行批量作业调度,并且可以方便地调整参数以适应不同规模的应用环境要求[^2]。 #### 借助 `Future<V>` 获取返回结果 对于那些希望得到具体计算成果而非仅仅关注过程本身的情况,则可以通过向 `submit(Callable<T> task)` 提交带有产出型签名的目标函数从而获得一个代表未来可能存在的输出凭证实例 —— 即泛型化的 `Future<V>` 对象用于稍后查询实际值是否存在以及尝试读取它们: ```java import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; // Define callable task that returns an integer result upon completion. static class Summation implements Callable<Integer> { private final int n; Summation(int numTerms) { this.n = numTerms; } @Override public Integer call() throws Exception { int sum = 0; for (int k=1 ;k<=this.n;++k){ sum += k; } return sum; } } ... try{ Future<Integer> futureResult = executor.submit(new Summation(100)); doOtherStuff(); // Do other things meanwhile if(futureResult.isDone()){ System.out.println("Sum of first hundred natural numbers:"+futureResult.get()); } }catch(Exception ex){ ex.printStackTrace(); }finally{ executor.shutdownNow(); } ``` 这里展示了一个简单的累加器作为示范案例说明了怎样结合使用回调模式与延迟求值特性共同作用下达到既保持灵活性又不失效率的目的[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值