Last Updated:

Jakarta 并发:现在和未来

银狐 java

Jakarta EE(以前称为 Java EE)是一组规范,使全球 Java 开发人员社区能够开发云原生 Java 企业应用程序。它是一个由Eclipse 基金会维护的开源项目

Jakarta Concurrency 是 Jakarta EE 保护伞下的一个小而基本的规范。作为项目负责人,我提供了更多关于它是什么、它的未来以及如何参与的信息。

为什么需要并发?

在 Java 中编程时,当您在不同线程之间移动时,您需要考虑应用程序的上下文级别。例如,如果您已登录 REST API,然后需要在新线程上创建任务,则需要保留安全上下文。要在Java SE 中做到这一点,您需要使用并发原语:与并发、多线程和并行相关的代码单元。

如果您在 Java SE 中生成一个新线程,Jakarta EE 运行时不知道该线程,并且将难以建立其安全(或类加载器或 CDI 等)上下文。

这就是 Jakarta Concurrency 的用武之地。它更新了 Java SE 并发原语,以便在 Jakarta EE 环境中使用。例如,Java SE Executor Service 变为 Managed Executor Service,具有相同的 API。这些类似的并发原语允许您在应用程序服务器中使用 Java SE 并发度量。

Jakarta EE 并发提供了 Java SE 和 Jakarta EE 平台之间的一致性,以实现从 SE 到 EE 的简单迁移路径。它还允许您使用并发设计原则轻松设计新的 Jakarta EE 应用程序,并将并发添加到 Jakarta EE 应用程序服务器中的现有应用程序。

Jakarta EE 旨在让开发人员能够专注于业务逻辑代码,带走基础设施和运营任务。其中一项任务是线程管理。因此,Jakarta Concurrency 允许您在托管的 Jakarta EE 运行时访问这些。

用例 1:在应用程序中添加异步任务

在 Jakarta Concurrency 出现之前,Java EE 开发人员需要使用 JMS 将异步任务构建到应用程序中。进入 servlet 或 REST 端点的 HTTP 请求需要长时间运行的操作作为响应,需要打包请求信息并使用消息驱动的 bean 将其推送到 JMS 队列中。这是一个重量级的过程。

Jakarta Concurrency 使这变得更简单。如果您有 HTTP 请求,您可以使用与在 Java SE 中相同的组件,但在 Java EE 版本中:Managed Executor Service。您将向此提交作业,这将在托管线程中运行以替换您长时间运行的操作。该线程将由 Jakarta 运行时管理,并将 REST 请求中的相同上下文应用于操作。因此,它的重量要轻得多。

在代码形式中,这看起来像这样,提供了比使用 JMS 简单得多的代码:

@Path("concurrency")
@RequestScoped
public class GenericResource {

   @Context
   private UriInfo uriInfo;

   @Resource
   private ManagedExecutorService managedExecutor;

   @GET
   @Path("simpleJob")
   @Produces(MediaType.TEXT_PLAIN)
   public String getText() {
      managedExecutor.submit(() -> {
         System.out.println("Job running");
      });
      return "Job Submitted";
   }
}

 

用例 2:并行运行任务 

您可能有一个 REST 请求进来,并希望并行运行两个任务,合并结果并将其返回给用户。使用 Jakarta Concurrency,您可以将 Managed Executor Service 注入您的 REST 端点,然后您可以使用 Managed Executor API 一次提交两个作业。该方法立即返回,您将返回 Future 类的一个实例。您可以通过调用get()方法获取作业的结果并将其合并,然后返回给用户。

以前,这将非常困难,需要 JMS,并且需要创建关联 ID。使用 Jakarta Concurrency,生成的代码如下所示:

@GET
@Path("parallelJob")
@Produces(MediaType.TEXT_PLAIN)
public String getParallelJob() throws ExecutionException, InterruptedException {
   Future future1 = managedExecutor.submit(() -> {
         System.out.println("Job 1 running ...");
         // This takes some while
         System.out.println("Job 1 finished ...");
      });
   Future future2 = managedExecutor.submit(() -> {
         System.out.println("Job 2 running ...");
         // This takes some while
         System.out.println("Job 2 finished ...");
   });
   future1.get(); // Wait for job to finish and get result (optionally)
   future2.get();
   return "Jobs completed";
}

Jakarta 并发的主要组成部分是什么?

  • 托管执行者服务

Jakarta EE 中的 Managed Executor Service 映射到 Java SE 中的 Executor Service,Managed Scheduled Executor Service 映射到 Scheduled Executive Service(如您在上面的用例中所见)。API 是相同的,但任务在 Jakarta EE 所需的上下文中运行。

  • 托管线程工厂 

Jakarta EE 中的托管线程工厂映射到 Java SE 中的线程工厂。当您拥有创建自己的线程但不了解 Jakarta EE的 API 时,可以使用此方法。您可以传入一个线程工厂。这允许您调用不知道 Jakarta 并发但将线程工厂作为参数的 API 或库。使用托管线程工厂,当创建一个在线程上运行的任务时,它会再次设置正确的上下文。

  • 上下文服务

上下文服务使您能够包装您的Runnable,创建一个上下文代理以提交给任何原始线程。它将建立您期望的所有上下文,因此对于您使用的 API 或库不了解 Jakarta EE 但正在生成线程时非常有用。

Jakarta Concurrency 的未来展望

Jakarta Concurrency 于 2013 年在 Java EE 7 中出现。与其他规范一样,它随着Jakarta EE 9版本移入 Jakarta EE 命名空间,并在Jakarta EE 9.1 中与 Java SE 11 兼容。现在转换已经完成,可以开始对规范进行实质性的功能更改。

开发中的一些想法(可在GitHub 中查看)是:

  • 可部署的托管对象 

当前,所有托管对象(默认对象除外)都必须由应用程序服务器管理员创建。

Jakarta EE 9 具有可部署的应用程序范围数据源。这里建议的功能是您可以设置自己的应用程序范围和配置的托管执行程序服务。这些将使用注释进行部署。

如果您的应用程序确实需要对线程、并发和线程池进行细粒度控制,则此功能将允许您在不需要管理控制台的情况下设置这些进程。

  • 新的@Asynchronous 注解 

目前,Jakarta EE 中有用于指示异步执行的注释,但它们非常特定于每个单独的规范。这建议新注释可以与 CDI Beans 一起使用。添加并能够配置执行程序服务池将在与可部署的执行程序服务相结合时实现细粒度的并发管理。例如,您可以为不同的方法选择不同的线程池。

这个新功能最终可能会导致所有规范通用的单个 @Asynchronous 注释。这将简化平台并使其更加统一。

  • 赶上 java.until.concurrent

Jakarta Concurrency 是在 Java EE 7 中发布的,因此尚未更新以匹配 Java SE 9、11 和 17 中引入的并发原语。其中一些包括以标准方式支持 ForkJoinPool,以及针对当前更新的 API Java SE 托管执行程序服务。

参与其中! 

作为 Jakarta Concurrency 的项目负责人,我的目标不是定义它的未来,而是领导一个可以推动规范向前发展的社区小组。简而言之,我需要您的帮助来实现规范!

每个规范都需要产生一个规范文档,详细说明你如何使用API​​;一个 API JAR,作为开发人员进行编码;和技术兼容性工具包 (TCK),该测试套件用于确定 API 的独立实现是否满足其要求。

您可以参与该过程的每个部分。例如,如果您对测试感兴趣,您可以帮助构建测试或维护 TCK。您还可以直接在 API 上提供帮助,确定作为开发人员需要哪些功能。还需要围绕规范文档提供帮助,从提交拼写错误的 PR 到更高级别的输入。

整个项目都在 GitHub 上,您可以在那里进行 API 更改:

雅加达并发 GitHub在这里找到 Eclipse 项目:

雅加达并发 Eclipse 项目

加入邮件列表: 

雅加达并发邮件列表
GitHub 上还有一个兼容实现,用于 GlassFish 和 Payara:
并发兼容实现 参与开源项目似乎令人生畏,但 Jakarta Concurrency 正在积极寻求各种帮助。如果有疑问 - 参与其中!

作者:史蒂夫米利奇