ExecutorService
和ScheduledExecutorService
都是Java的java.util.concurrent
包中的接口,用于控制和管理线程,但是,这两个接口在功能和用途上有一些关键的区别:
1、ExecutorService
ExecutorService
是一个用于管理和控制线程的接口,它提供了一种将任务提交与每个任务将如何运行的机制(包括线程细节)分离开来的方法,使得并发编程开发变得更简单,可以创建一个固定大小的线程池,或者让ExecutorService
根据需要创建新的线程,提交给ExecutorService
的任务通常会立即开始执行。
2、ScheduledExecutorService
ScheduledExecutorService
是ExecutorService
的一个子接口,它提供了在给定延迟后执行命令,或者定期执行命令的能力,可以安排任务在未来的某个时间开始执行,或者以固定的时间间隔重复执行。ScheduledExecutorService
对于需要定时任务或者周期性任务的应用来说非常有用。
3、个人总结
ExecutorService
它允许提交任务并控制它们如何运行,但是,它不提供定时或周期性任务的功能。ScheduledExecutorService
扩展了ExecutorService
的功能,允许在未来的某个时间点执行任务,或者以固定的频率重复执行任务。
使用ExecutorService
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorServiceExample {
public static void main(String[] args) {
// 创建一个固定大小的线程池
ExecutorService executorService = Executors.newFixedThreadPool(4);
// 提交任务到线程池
for (int i = 0; i < 10; i++) {
final int taskId = i;
executorService.submit(() -> {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
});
}
// 关闭线程池(这里为了演示,实际上可能需要等待所有任务完成后再关闭)
// executorService.shutdown();
// 注意:在实际应用中,通常会想要等待所有任务完成后再关闭线程池。
// 可以通过调用executorService.awaitTermination或者其他方法来等待任务完成。
}
}
上面代码中,创建了一个包含4个线程的线程池,然后提交了10个任务到线程池,每个任务就是一个简单的Runnable
,它打印出任务ID和执行任务的线程名。
使用ScheduledExecutorService
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorServiceExample {
public static void main(String[] args) {
// 创建一个ScheduledExecutorService实例
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
// 提交一个延迟3秒后执行的任务
scheduledExecutorService.schedule(() -> {
System.out.println("Delayed task executed after 3 seconds");
}, 3, TimeUnit.SECONDS);
// 提交一个立即执行然后每隔1秒重复执行的任务
scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println("Repeating task executed every 1 second");
}, 0, 1, TimeUnit.SECONDS);
// 注意:在实际应用中,应该在不再需要ScheduledExecutorService时将其关闭,
// 但在这个例子中,让任务无限期地执行下去。在实际情况下,可能会有适当的停止条件。
// 为了避免程序立即退出,在这里简单地等待一段时间,让任务有机会执行。
// 这只是为了演示,并不是推荐的做法。
try {
Thread.sleep(10000); // 等待10秒,让上面的任务有机会执行几次
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭ScheduledExecutorService
scheduledExecutorService.shutdown();
try {
if (!scheduledExecutorService.awaitTermination(800, TimeUnit.MILLISECONDS)) {
scheduledExecutorService.shutdownNow();
}
} catch (InterruptedException e) {
scheduledExecutorService.shutdownNow();
}
}
}
上面代码中创建了一个ScheduledExecutorService
实例,并指定了线程池的大小为2,然后,提交了两个任务:一个延迟3秒后执行,另一个立即执行并每隔1秒重复执行。