加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

鸟瞰 Java 并发框架

发布时间:2019-07-18 16:22:42 所属栏目:优化 来源:唐尤华
导读:1. 为什么要写这篇文章 几年前 NoSQL 开始流行的时候,像其他团队一样,我们的团队也热衷于令人兴奋的新东西,并且计划替换一个应用程序的数据库。但是,当深入实现细节时,我们想起了一位智者曾经说过的话:细节决定成败。最终我们意识到 NoSQL 不是解决

如果没有 AsyncResponse,性能与 ExecutorService 相同。如果多个 API 调用必须异步并且链接起来,那么这种方法更好(类似 Node 中的 Promises)。

  1. ExecutorService ioExecutorService = CustomThreads.getExecutorService(ioPoolSize); 
  2.  
  3. // I/O 任务 
  4. CompletableFuture<String> postsFuture = CompletableFuture.supplyAsync(JsonService::getPosts, ioExecutorService); 
  5. CompletableFuture<String> commentsFuture = CompletableFuture.supplyAsync(JsonService::getComments, 
  6.     ioExecutorService); 
  7. CompletableFuture<String> albumsFuture = CompletableFuture.supplyAsync(JsonService::getAlbums, 
  8.     ioExecutorService); 
  9. CompletableFuture<String> photosFuture = CompletableFuture.supplyAsync(JsonService::getPhotos, 
  10.     ioExecutorService); 
  11. CompletableFuture.allOf(postsFuture, commentsFuture, albumsFuture, photosFuture).get(); 
  12.  
  13. // 从 I/O 任务(阻塞调用)获得响应 
  14. String posts = postsFuture.get(); 
  15. String comments = commentsFuture.get(); 
  16. String albums = albumsFuture.get(); 
  17. String photos = photosFuture.get(); 
  18.  
  19. // 合并响应(内存中的任务将是此操作的一部分) 
  20. String postsAndCommentsOfRandomUser = ResponseUtil.getPostsAndCommentsOfRandomUser(userId, posts, comments); 
  21. String albumsAndPhotosOfRandomUser = ResponseUtil.getAlbumsAndPhotosOfRandomUser(userId, albums, photos); 
  22.  
  23. // 构建最终响应并将其发送回客户端 
  24. return postsAndCommentsOfRandomUser + albumsAndPhotosOfRandomUser; 

7. 使用 ExecutorService 并行处理所有任务

使用 ExecutorService 并行处理所有任务,并使用 @suspended AsyncResponse response 以非阻塞方式发送响应。

鸟瞰 Java 并发框架

图片来自 http://tutorials.jenkov.com/java-nio/nio-vs-io.html

  • HTTP 线程处理传入请求的连接,并将处理传递给 Executor Pool,当所有任务完成后,另一个 HTTP 线程将把响应发送回客户端(异步非阻塞)。
  • 性能下降原因:
    • 在同步通信中,尽管 I/O 任务中涉及的线程被阻塞,但是只要进程有额外的线程来承担并发请求负载,它仍然处于运行状态。
    • 因此,以非阻塞方式保持线程所带来的好处非常少,而且在此模式中处理请求所涉及的成本似乎很高。
    • 通常,对这里讨论采用的例子使用异步非阻塞方法会降低应用程序的性能。

7.1 何时使用?

如果用例类似于服务器端聊天应用程序,在客户端响应之前,线程不需要保持连接,那么异步、非阻塞方法比同步通信更受欢迎。在这些用例中,系统资源可以通过异步、非阻塞方法得到更好的利用,而不仅仅是等待。

  1. // 为异步执行提交并行任务 
  2. ExecutorService ioExecutorService = CustomThreads.getExecutorService(ioPoolSize); 
  3. CompletableFuture<String> postsFuture = CompletableFuture.supplyAsync(JsonService::getPosts, ioExecutorService); 
  4. CompletableFuture<String> commentsFuture = CompletableFuture.supplyAsync(JsonService::getComments, 
  5. ioExecutorService); 
  6. CompletableFuture<String> albumsFuture = CompletableFuture.supplyAsync(JsonService::getAlbums, 
  7. ioExecutorService); 
  8. CompletableFuture<String> photosFuture = CompletableFuture.supplyAsync(JsonService::getPhotos, 
  9. ioExecutorService); 
  10.  
  11. // 当 /posts API 返回响应时,它将与来自 /comments API 的响应结合在一起 
  12. // 作为这个操作的一部分,将执行内存中的一些任务 
  13. CompletableFuture<String> postsAndCommentsFuture = postsFuture.thenCombineAsync(commentsFuture, 
  14. (posts, comments) -> ResponseUtil.getPostsAndCommentsOfRandomUser(userId, posts, comments), 
  15. ioExecutorService); 
  16.  
  17. // 当 /albums API 返回响应时,它将与来自 /photos API 的响应结合在一起 
  18. // 作为这个操作的一部分,将执行内存中的一些任务 
  19. CompletableFuture<String> albumsAndPhotosFuture = albumsFuture.thenCombineAsync(photosFuture, 
  20. (albums, photos) -> ResponseUtil.getAlbumsAndPhotosOfRandomUser(userId, albums, photos), 
  21. ioExecutorService); 
  22.  
  23. // 构建最终响应并恢复 http 连接,把响应发送回客户端 
  24. postsAndCommentsFuture.thenAcceptBothAsync(albumsAndPhotosFuture, (s1, s2) -> { 
  25. LOG.info("Building Async Response in Thread " + Thread.currentThread().getName()); 
  26. String response = s1 + s2; 
  27. asyncHttpResponse.resume(response); 
  28. }, ioExecutorService); 

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读