- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
在 Spring 中,您可以让 Controller 返回一个 Callable 而不是 T,这将立即释放请求处理线程并在 WebAsyncManager 管理的 MvcAsync 线程中计算结果。您只需要将 Controller 方法内容包装在 return () -> {... return result; };
。非常简单!
但这有什么意义呢?
有什么区别?a) 拥有 500 个请求处理线程并让它们完成所有工作并且
b) 只有几个请求处理线程并在 concurrencyLimit 为 500 的 Callables 中执行所有请求?
第二个选项 b) 实际上对我来说看起来更糟,因为管理整个 MvcAsync 魔法涉及开销。
我知道如何收获 @Async 方法来一次执行两个方法并在两个方法完成后返回结果,但我显然不理解 Callable Controller 方法。
最佳答案
假设您有一个 Tomcat 服务器,它有 10 个线程监听客户端请求。如果您有一个客户端调用一个需要 5 秒响应的端点,那么该客户端会在这 5 秒内保持该线程。添加几个并发客户端,您很快就会在这 5 秒内耗尽线程。
情况更糟,因为在这 5 秒的大部分时间里,您的请求主要是在执行 I/O,这意味着您只是阻塞您的线程,除了等待什么都不做。
所以,Spring能够使用Callable、CompletableFuture或ListenableFuture作为 Controller 的返回类型,正是为了让程序员在一定程度上克服这种问题。
从根本上说,仅返回其中一种类型只会释放 Web 服务器线程,使其可供另一个客户端使用。因此,您可以在相同的时间内接待更多的客户,但是,这本身可能不足以实现非阻塞 IO(又名 NIO)API。
这些特性中的大部分来自 Servlet API 和 Servlet Async IO 提供的核心功能,Spring 应该在底层使用它们。您可能想看看以下有趣的视频,它们帮助我从头开始理解这一点:
这些视频解释了 Servlet Async I/O 背后的想法以及实现 NIO Web 应用程序的最终目标。
这里的 chalice 是达到这样一个点,即线程池中的线程永远不会阻塞等待某些 I/O 发生。它们要么在做一些 CPU 密集型工作,要么回到线程池中供其他客户端使用。当您执行 I/O 时,您不会引入等待,您注册某种形式的回调,用于在结果准备好时通知您,同时您可以使用您宝贵的 CPU 核心来处理其他事情。如果您仔细考虑,Callable、CompletableFuture 或 ListenableFuture 是 Spring 基础架构在后台使用的那种回调对象,用于调用它们的功能以在单独的线程中处理请求。
这会增加您的吞吐量,因为您可以同时处理更多的客户端,只需优化您宝贵的 CPU 资源的使用,特别是如果您以 NIO 方式执行此操作,因为您可以想象,只需将请求移至另一个线程,虽然有益(因为您释放了一个有值(value)的 Tomcat 线程),但仍然会阻塞,因此,您只是将问题转移到另一个线程池。
我相信这个基本原则也是 Spring 团队目前在 Project Reactor 中所做工作的很大一部分背后的原因。因为为了利用此类功能的强大功能,您需要在 API 中引入异步编程,而这很难做到。
这也是像 Netty 这样的框架激增的原因。 , RxJava , Reactive Streams Initiative和 Project Reactor .他们都在寻求推广这种优化和编程模型。
还有一个有趣的新框架运动,利用这个强大的特性,并试图与 Spring 竞争甚至补充 Spring 但在该领域的功能有限。我说的是有趣的项目,例如 Vert.x和 Ratpack现在我们开始了,这个功能是Node.js 的主要卖点之一。
关于java - 可调用/可运行 Controller 方法 : What's the point?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42076887/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!