Java Executors详解

Java的多线程编程一直被广泛使用和研究。它提供了许多方式来管理和控制线程的行为。但是这些功能并不足以方便地进行线程管理。在这种情况下,Java的并发库提供了一种解决办法,即使用java.util.concurrent.Executors类来管理线程。它使线程管理变得更加简单、易于理解和实现。本文将从多个方面对Java Executors进行详细的介绍。

一、线程池

线程池是一种执行多个任务的方式,使用线程池可以避免创建线程的开销,以及将任务排队等待的时间,从而提高程序的响应速度和性能。Java的线程池管理器类是java.util.concurrent.ExecutorService接口。下面是一个实现线程池的示例:

“`java
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new MyRunnable(i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
“`

这里使用newFixedThreadPool方法创建一个固定大小的线程池。该线程池有5个线程。然后,循环运行10个任务。这些任务由MyRunnable类实现,实现了Runnable接口。execute()方法将每个任务提交给线程池,线程池会从线程池中的空闲线程中选择一个线程来执行它们。最后,关闭线程池,并等待所有任务完成。注意,这里的线程池最大可用线程数是5个。如果提交10个任务,则前5个将立即开始,而剩余5个任务将排队等待线程可用。

二、ScheduledExecutorService

Java的ScheduledExecutorService接口提供了一种调度执行任务的机制。下面是一个使用ScheduledExecutorService的示例:

“`java
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
ScheduledFuture scheduledFuture =
executor.scheduleAtFixedRate(new MyRunnable(), 1, 5, TimeUnit.SECONDS);
“`

这里创建了一个大小为2的ScheduledExecutorService。然后使用scheduleAtFixedRate方法将任务提交给它。任务由MyRunnable实现。scheduleAtFixedRate表示每隔5秒钟执行一次任务。这里,需要注意的是,它初始延迟时间为1秒,因此,任务将在1秒后就开始执行。返回值是ScheduledFuture,它表示定期调度任务的结果和控制。可以使用以下代码取消执行:

“`java
scheduledFuture.cancel(true);
“`

三、Callable和Future

Callable是一个带有类型参数的接口,可以使用它来执行一个返回类型的异步任务。上面的代码已经使用了Runnable测试任务的执行。Callable并行计算的执行可以使用Future类。Future是一个带有类型参数的接口,用于获取并处理异步任务的结果。

下面是一个使用Callable和Future的示例:

“`java
ExecutorService executor = Executors.newSingleThreadExecutor();
Future future = executor.submit(new Callable() {
@Override
public Integer call() throws Exception {
int count = 0;
for (int i = 0; i < 100; i++) {
count += i;
}
return count;
}
});
try {
System.out.println("result : " + future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
“`

这里,使用newSingleThreadExecutor方法创建一个只有单个线程的线程池。这个线程池将执行一个返回类型为Integer的异步任务,这个任务是一个Callable实现。submit()方法提交任务,并返回一个Future对象。然后,通过调用get()方法等待异步任务完成并获取结果。最后,关闭线程池。

四、CompletionService

CompletionService是一种在完成任务时返回结果的一种更高级的机制。CompletionService表示处理线程执行结果的一组队列。它提供了一个带有队列的ExecutorService的实现,可以使用它来获取已完成任务的结果。CompletionService和Future都可以用于获取任务的结果,但CompletionService可以更多地控制任务的执行和获取它们的结果。

下面是一个使用CompletionService的示例:

“`java
ExecutorService executor = Executors.newFixedThreadPool(5);
CompletionService completionService = new ExecutorCompletionService(executor);
for (int i = 0; i < 10; i++) {
final int taskId = i;
completionService.submit(new Callable() {
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
return taskId;
}
});
}
for (int i = 0; i < 10; i++) {
try {
System.out.println(completionService.take().get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
“`

这里创建一个固定大小为5的线程池。然后,使用ExecutorCompletionService代替CompletionService,以将任务提交给它。这个示例将提交执行10个任务,每个任务执行2秒钟。当任务完成时,take()方法将返回一个Future对象。使用get()方法等待异步任务完成并获取它的结果。最后,关闭线程池。

五、ForkJoinPool

Java的ForkJoinPool类是一个特殊的线程池,它可以重用线程,以便更好地利用CPU和内存资源。ForkJoinPool的主要设计目标是支持分治任务,例如在QuickSort或合并排序中使用。下面是一个使用ForkJoinPool的示例:

“`java
class ForkJoinMergeSort<T extends Comparable> extends RecursiveAction {
private T[] array;
private int start;
private int end;

public ForkJoinMergeSort(T[] array, int start, int end) {
super();
this.array = array;
this.start = start;
this.end = end;
}

@Override
protected void compute() {
if (end – start < 2) {
return;
}
int middle = (start + end) / 2;
invokeAll(new ForkJoinMergeSort(array, start, middle),
new ForkJoinMergeSort(array, middle, end));
merge(array, start, middle, end);
}

private void merge(T[] array, int start, int middle, int end) {
T[] tempArray = (T[]) new Comparable[end – start];
int i = start;
int j = middle;
int k = 0;
while (i < middle && j < end) {
tempArray[k++] = array[i].compareTo(array[j]) < 0 ? array[i++] : array[j++];
}
while (i < middle) {
tempArray[k++] = array[i++];
}
while (j < end) {
tempArray[k++] = array[j++];
}
System.arraycopy(tempArray, 0, array, start, tempArray.length);
}
}

public class ForkJoinPoolDemo {
public static void main(String[] args) {
Integer[] array = { 3, 56, 23, 1, 5, 34, 78, 2, 45, 99 };
ForkJoinPool pool = new ForkJoinPool();
ForkJoinMergeSort task = new ForkJoinMergeSort(array, 0, array.length);
pool.invoke(task);
pool.shutdown();
System.out.println(Arrays.toString(array));
}
}
“`

这里实现一个单核心的归并排序算法,并使用ForkJoinPool类执行算法。ForkJoinPool从内部维护线程池,递归地拆分任务,将它们分配给可用的线程,当线程完成任务时将结果汇总。在这里,元素列表被递归地划分为子列表,直到列表元素数量为1,然后逐步合并这些子列表,直到完成排序。

以上就是Java Executors的详细介绍。它是Java多线程编程中的一个重要组成部分,并且提供了许多有用的实用程序,使线程编程变得更加容易和高效。

原创文章,作者:SMPB,如若转载,请注明出处:https://www.506064.com/n/143624.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
SMPBSMPB
上一篇 2024-10-22 23:34
下一篇 2024-10-22 23:34

相关推荐

  • Java JsonPath 效率优化指南

    本篇文章将深入探讨Java JsonPath的效率问题,并提供一些优化方案。 一、JsonPath 简介 JsonPath是一个可用于从JSON数据中获取信息的库。它提供了一种DS…

    编程 2025-04-29
  • java client.getacsresponse 编译报错解决方法

    java client.getacsresponse 编译报错是Java编程过程中常见的错误,常见的原因是代码的语法错误、类库依赖问题和编译环境的配置问题。下面将从多个方面进行分析…

    编程 2025-04-29
  • Java Bean加载过程

    Java Bean加载过程涉及到类加载器、反射机制和Java虚拟机的执行过程。在本文中,将从这三个方面详细阐述Java Bean加载的过程。 一、类加载器 类加载器是Java虚拟机…

    编程 2025-04-29
  • Java腾讯云音视频对接

    本文旨在从多个方面详细阐述Java腾讯云音视频对接,提供完整的代码示例。 一、腾讯云音视频介绍 腾讯云音视频服务(Cloud Tencent Real-Time Communica…

    编程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介绍

    本文将详细介绍Java Milvus SearchParam withoutFields的相关知识和用法。 一、什么是Java Milvus SearchParam without…

    编程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java语言中的一个版本,于2014年3月18日发布。本文将从多个方面对Java 8中某一周的周一进行详细的阐述。 一、数组处理 Java 8新特性之一是Stream…

    编程 2025-04-29
  • Java判断字符串是否存在多个

    本文将从以下几个方面详细阐述如何使用Java判断一个字符串中是否存在多个指定字符: 一、字符串遍历 字符串是Java编程中非常重要的一种数据类型。要判断字符串中是否存在多个指定字符…

    编程 2025-04-29
  • VSCode为什么无法运行Java

    解答:VSCode无法运行Java是因为默认情况下,VSCode并没有集成Java运行环境,需要手动添加Java运行环境或安装相关插件才能实现Java代码的编写、调试和运行。 一、…

    编程 2025-04-29
  • Java任务下发回滚系统的设计与实现

    本文将介绍一个Java任务下发回滚系统的设计与实现。该系统可以用于执行复杂的任务,包括可回滚的任务,及时恢复任务失败前的状态。系统使用Java语言进行开发,可以支持多种类型的任务。…

    编程 2025-04-29
  • Java 8 Group By 会影响排序吗?

    是的,Java 8中的Group By会对排序产生影响。本文将从多个方面探讨Group By对排序的影响。 一、Group By的概述 Group By是SQL中的一种常见操作,它…

    编程 2025-04-29

发表回复

登录后才能评论