介绍

Java EE具有许多API和构造以支持异步执行。 从可伸缩性和性能的角度来看,这是至关重要的。

让我们假设2个模块相互交互。 当模块A (发送方)以同步方式向模块B (接收方)发送消息时,通信将在单个线程的上下文中进行,即,从模块A发起通信的线程将被阻塞,直到模块B作出响应为止。

这是一个通用的声明,但可以扩展到一个简单的Java方法相互交融的背景下-在这种情况下,从了methodA的methodB 同步调用将在同一个 线程执行这将被阻塞,直到的methodB返回或抛出一个异常。

为什么在基于Java EE的应用程序中需要异步行为?

我们可以进一步将这一点推算到Java EE领域-服务器之间的通信,例如Web层和EJB层(Servlet和EJB)之间的通信,或者是典型的客户端服务器交互-浏览器与RESTful端点,Servlet等的交互-服务器响应客户端请求的线程始终阻塞,直到服务器组件响应。

异步执行在这里发挥作用-如果可以释放/暂停处理客户请求的服务器线程 ,并且在单独的线程中执行实际的业务逻辑(与原始线程不同),则可以极大地提高性能和可伸缩性。 ! 例如,如果分配给侦听客户端请求的HTTP侦听器线程被立即释放,则可以自由地处理来自其他客户端的请求,并且可以在单独的容器线程中执行业务逻辑,然后该容器线程可以通过适当的方法(例如, java.util.concurrent.Future对象或通过客户端注册的回调处理程序 。 从最终用户的角度考虑- 响应非常重要!

深入研究:Java EE中的异步构造和API

让我们看一下Java EE中的一些异步相关功能(API)。 这不是一个详尽的列表,但是应该是一个很好的起点。

不同的Java EE规范具有促进异步功能的典型方式和API。 让我们探索以下Java EE规范

  • JAX-RS 2.0(Java EE 7)
  • Websocket 1.0(Java EE 7)
  • 并发实用工具1.0(Java EE 7)
  • EJB 3.1(Java EE 6)
  • Servlet 3.0(Java EE 6)

注意 :下面提供的代码为摘要形式(出于明显的原因)。 完整的样本可以在这里访问 。

JAX-RS 2.0

请求的异步处理是JAX-RS 2.0版 (Java EE 7中的新增功能 )的一项新功能 。 为了使用JAX-RS API执行aysnc请求,需要在JAX-RS资源方法本身中注入对javax.ws.rs.container.AsyncResponse接口的引用。 此参数将请求执行置于异步模式,然后该方法继续执行。 业务逻辑执行完成后,需要从单独的线程中调用AsynResponse对象上的resume方法。 可以利用Java EE并发实用程序功能(稍后讨论),例如javax.enterprise.concurrent.ManagedExecutorService ,以将业务逻辑封装为Runnable对象,并将其提交给容器的执行者服务,其余部分由该服务执行。 无需自己产生不受管理的隔离线程。

@Path("/{id}")@GET@Produces("application/xml")public void asyncMethod(@Suspended AsyncResponse resp, @PathParam("id") String input) {System.out.println("Entered MyAsyncRESTResource/asyncMethod() executing in thread: "+ Thread.currentThread().getName());mes.execute(() -> {System.out.println("Entered Async zone executing in thread: "+ Thread.currentThread().getName());System.out.println("Simulating long running op via Thread sleep() started on "+ new Date().toString());try {Thread.sleep(5000);} catch (InterruptedException ex) {Logger.getLogger(MyAsyncRESTResource.class.getName()).log(Level.SEVERE, null, ex);}System.out.println("Completed Long running op on "+new Date().toString());System.out.println("Exiting Async zone executing in thread: "+ Thread.currentThread().getName());//creating a dummy instance of our model class (Student)Student stud = new Student(input, "Abhishek", "Apr-08-1987");resp.resume(Response.ok(stud).build());});System.out.println("Exit MyAsyncRESTResource/asyncMethod() and returned thread "+Thread.currentThread().getName()+" back to thread pool");}

JAX-RS客户端API也具有异步功能,但本文未对此进行讨论。 他们绝对值得一看!

Websocket 1.0

Websocket API是Java EE工具库(Java EE 7中引入)的全新添加 。 它促进了双向 (服务器和客户端发起的)通信的本质上也是全双工的(客户端或服务器都可以在任何时候相互发送消息)。

为了使用Websocket API发送异步消息,需要使用javax.websocket.Session接口上可用的getAsyncRemote方法。 在内部,这不过是javax.websocket.RemoteEnpointjavax.websocket.RemoteEnpoint.Async的嵌套接口的实例。 对此调用常规的sendXXX方法将导致发送过程在单独的线程中执行。 当您考虑交换大消息或处理需要向其发送消息的大量Websocket客户端时,这特别有用。 枯萎的方法返回一个java.util.concurrent.Future对象,或者可以以javax.websocket.SendHandler接口实现的形式注册一个回调。

public void sendMsg(@Observes Stock stock) {System.out.println("Message receieved by MessageObserver --> "+ stock);System.out.println("peers.size() --> "+ peers.size());peers.stream().forEach((aPeer) -> {//stock.setPrice();aPeer.getAsyncRemote().sendText(stock.toString(), (result) -> {System.out.println("Message Sent? " + result.isOK());System.out.println("Thread : " + Thread.currentThread().getName());});});}

并发实用工具1.0

Java EE并发实用程序是Java EE 7的另一个重要补充 。 它提供了一种标准的生成线程的方式–好的方面是,这些线程是容器管理的而不仅仅是容器没有上下文信息的孤立/孤立线程

通常,并发实用工具1.0提供了一些用于在单独线程中执行异步任务的标准构造。 它们如下: javax.enterprise.concurrent.ManagedExecutorService javax.enterprise.concurrent.ManagedScheduledExecutorService

为了在单独的线程中启动新任务,可以使用ManagedExecutorService接口提交Runnable 。 除了实现Runnable接口之外,类还可以实现javax.enterprise.concurrent.ManagedTask接口并提供javax.enterprise.concurrent.ManagedTaskListener实现,以便侦听通过ManagedExecutorService提交的任务的生命周期更改。

@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {System.out.println("Enter AConcurrencyUtilsExample/doGet executing in thread "+ Thread.currentThread().getName());System.out.println("initiating task . . . ");mes.execute(new AManagedTask());System.out.println("Exit AConcurrencyUtilsExample/doGet and returning thread "+ Thread.currentThread().getName() +" back to pool");}

Servlet 3.0

Servlet 3.0( Java EE 6的一部分)中引入了异步HTTP,它基本上提供了在单独的线程中执行请求并挂起处理客户端调用的原始线程的功能。

这里的关键角色是javax.servlet.AsyncContext接口。 为了启动异步处理,调用java.servlet.ServletRequest接口的startAsync方法。 为了执行核心逻辑,需要将java.lang.Runnable对象提交给AsyncContext接口的start方法。 可以选择通过实现javax.servlet.AsyncListener来附加侦听器,以便在Async任务执行的特定时间接收回调通知。

@Overridepublic void doGet(HttpServletRequest req, HttpServletResponse resp) {PrintWriter writer = null;try {writer = resp.getWriter();} catch (IOException ex) {Logger.getLogger(MyAsyncServlet.class.getName()).log(Level.SEVERE, null, ex);}//System.out.println("entered doGet()");writer.println("ENTERING ... " + MyAsyncServlet.class.getSimpleName() + "/doGet()");writer.println("Executing in Thread: " + Thread.currentThread().getName());//step 1final AsyncContext asyncContext = req.startAsync();//step 2asyncContext.addListener(new CustomAsyncHandler(asyncContext));//step 3asyncContext.start(() -> {PrintWriter logger = null;try {logger = asyncContext.getResponse().getWriter();} catch (IOException ex) {Logger.getLogger(MyAsyncServlet.class.getName()).log(Level.SEVERE, null, ex);}logger.println("Long running Aync task execution started : " + new Date().toString());logger.println("Executing in Thread: " + Thread.currentThread().getName());try {Thread.sleep(5000);} catch (InterruptedException e) {Logger.getLogger(MyAsyncServlet.class.getName()).log(Level.SEVERE, null, e);}logger.println("Long task execution complete : " + new Date().toString());logger.println("Calling complete() on AsyncContext");//step 4asyncContext.complete();});writer.println("EXITING ... " + MyAsyncServlet.class.getSimpleName() + "/doGet() and returning initial thread back to the thread pool");}

EJB 3.1

通常,(在EJB 3.1之前)EJB消息驱动Bean用于满足与异步相关的要求。 MDB bean侦听发送到javax.jms.Destination队列Topic )的消息,并执行所需的业务逻辑–从发送电子邮件到启动订单处理任务,这可能是任何事情。 要了解的重要一点是,首先将消息发送到Queue的客户端不知道 MDB(已解耦 ),并且不必等待/保持阻塞,直到作业结束(电子邮件收据或订单处理确认) )。

EJB 3.1( Java EE 6的一部分)引入了javax.ejb.Asynchronous批注。 可以将其放在EJB会话bean(无状态,有状态或单例) (使所有方法异步)上,也可以放在方法级别本身上(以防需要精细控制)。 如果需要跟踪异步方法的结果,则带有@Asynchronous批注的方法可以返回void (失火并忘记)或java.util.concurrent.Future的实例–这可以通过调用Future.get()来完成–需要注意的是, get方法本身实际上是阻塞的。

@Asynchronouspublic Future<String> asyncEJB2(){System.out.println("Entered MyAsyncEJB/asyncEJB2()");System.out.println("MyAsyncEJB/asyncEJB2() Executing in thread: "+ Thread.currentThread().getName());System.out.println("Pretending as if MyAsyncEJB/asyncEJB2() is doing something !");try {Thread.sleep(5000);} catch (InterruptedException ex) {java.util.logging.Logger.getLogger(MyAsyncEJB.class.getName()).log(Level.SEVERE, null, ex);}System.out.println("Exiting MyAsyncEJB/asyncEJB2()");return new AsyncResult("Finished Executing on "+ new Date().toString());}

这是Java EE功能的相当简短的预览。 这些API和规范功能丰富,很难通过博客文章涵盖所有这些API和规范! 我希望这能激起您的兴趣,并为您提供进一步探索的起点。

干杯!

翻译自: https://www.javacodegeeks.com/2014/08/java-ee-asynchronous-constructs-and-capabilities.html

Java EE:异步构造和功能相关推荐

  1. java ee打印功能_Java EE:异步构造和功能

    java ee打印功能 介绍 Java EE具有许多API和构造以支持异步执行. 从可伸缩性和性能的角度来看,这是至关重要的. 让我们假设2个模块相互交互. 当模块A (发送方)以同步方式向模块B ( ...

  2. Java EE 7:新增功能???

    我有点"晚点",可以这么说--就Java EE 7的 "博客"而言. 自2013年6月发布以来,已经差不多10个月了 ,但是它仍然相对较新. 就我个人而言,仅仅 ...

  3. java与java ee_RxJava + Java8 + Java EE 7 + Arquillian =幸福

    java与java ee 微服务是一种体系结构样式,其中每个服务都实现为一个独立的系统. 他们可以使用自己的持久性系统(尽管不是强制性的),部署,语言等. 由于系统由一个以上的服务组成,因此每个服务将 ...

  4. RxJava + Java8 + Java EE 7 + Arquillian =幸福

    微服务是一种体系结构样式,其中每个服务都实现为一个独立的系统. 他们可以使用自己的持久性系统(尽管不是强制性的),部署,语言等. 由于系统由一个以上的服务组成,因此每个服务将与其他服务通信,通常使用轻 ...

  5. Arun Gupta通过将HTML5与Java EE 7拥抱来提高生产力

    Oracle Java EE专家Arun Gupta简要介绍了Java EE7. 经Oracle公司Oracle技术网络的许可,转载. 在2013年1月14日至16日举行的年度IOUC(国际Oracl ...

  6. java ee7帮助文档_帮助推动Java EE向前发展

    java ee7帮助文档 如果您还记得我写的题为< Java EE 8:当前状态是什么>的文章 ,很明显,Java EE的发展无疑在过去几个月中有所放缓. 肯定有一些Java EE下的JS ...

  7. Java EE 7中的资源和依赖注入

    1.概述 上下文和依赖注入(CDI)是Java EE的一项功能,可帮助融合Java EE 6和更高版本中包含的平台的Web层和事务层. 从技术角度来看,这意味着CDI提供了依赖项注入框架,并且还管理了 ...

  8. xaas_从XaaS到Java EE – 2012年哪款该死的云最适合我?

    xaas 您是否曾经想过要使Java EE正常运行需要什么? 是的 多年. 从托管我自己的主机开始,转到一些托管产品 ,最后偶然发现了PaaS运动. 老实说,我并没有太认真. 我只是想把我的东西放到某 ...

  9. Java EE与Java SE:Oracle是否放弃了企业软件?

    Java Enterprise Edition是全球Java社区中最大的困惑来源之一. 就像<星球大战>和<星际迷航 >之间的区别一样,对于"原力觉醒"是他 ...

最新文章

  1. (转载) 数组a[]={3,5,2,4,1,8},要求从a中找出所有“和”等于10的子集
  2. 交换机背板带宽公式计算
  3. js的作用域链,原型链,以及闭包函数理解
  4. 如何从零开始开发一个实时联机游戏?
  5. HDU1421 搬寝室
  6. pyqt5 最小化 系统托盘_Qt中如何使窗口隐藏/最小化到托盘
  7. 【JAVA基础篇】Socket编程
  8. 一个程序员的日常,简直太欢乐了!
  9. php nginx 实时输出,phpnginx实时输出实现方法分享
  10. matlab std函数_如何利用Matlab进行小波分析
  11. 基于JAVA+SpringBoot+Mybatis+MYSQL的旅游信息管理系统
  12. Shell编程 之 while循环 和 until循环 和 总结
  13. C++ 推断进程是否存在
  14. 人脸检测(五)--adaboost总结,整理
  15. 论文推荐 | 一文了解百度10篇ACL 2019概况和该技术的实际可落地应用
  16. Docker 学习笔记
  17. 去除加粗的css,css如何取消加粗
  18. windows平台下载android源码
  19. php: 远程操作浏览器cookie存储入门
  20. WikiTaxi_Importer_1.3.1 维基 离线数据库

热门文章

  1. 八皇后问题判断此位置是否需合适
  2. arm linux gcc 编译,Linux arm-linux-gcc交叉编译环境配置
  3. gpu超算算法_超算安装GPU-based软件 (以pytorch为例)
  4. 局域网物理机怎么访问虚拟机
  5. compose应用_带有PostgreSQLDocker Compose for Spring Boot应用程序
  6. r2dbc_使用Spring Data R2DBC进行异步RDBMS访问
  7. 用jackson转json_用Jackson编写大JSON文件
  8. java自动生成类_自动生成优化的Java类专业知识
  9. logback redis_使用Spring Boot和Logback登录到Redis
  10. 使用Java EE 8中的反应式API加速服务