Urb*_*Urb 4 java inputstream nonblocking thread-local java-21
使用 java 21,只需在虚拟线程中执行即可将阻塞 IO 代码转换为非阻塞代码。
我应该简单地包装返回 an 的 HTTP 调用InputStream(如 method 中),还是在虚拟线程中nonBlockingA执行 the 的读取和反序列化(如 method 中)会更有效?InputStreamnonBlockingB
也就是说,读取是InputStream阻塞IO操作吗?
请记住,响应可能非常大,可能包含超过 500,000 个字符串。我也不确定所使用的库是否使用任何 ThreadLocals,这不推荐用于虚拟线程
@SuppressWarnings("unchecked")
class Request {
private final ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();
private CloseableHttpClient httpApacheClient;
List<String> nonBlockingA() throws Exception {
InputStream bigInputStream = executorService.submit(this::getResponse).get();
return deserialize(bigInputStream);
}
List<String> nonBlockingB() throws Exception {
return executorService.submit(() -> {
InputStream bigInputStream = getResponse();
return deserialize(bigInputStream);
}).get();
}
private InputStream getResponse() throws IOException {
return httpApacheClient.execute(new HttpGet("http://random/names/size/500000")).getEntity().getContent();
}
private static List<String> deserialize(InputStream body) throws IOException {
try (InputStreamReader reader = new InputStreamReader(body, UTF_8)) {
return new Gson().fromJson(reader, List.class);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您的变体之间没有显着差异。任何返回完整构造结果的方法,例如List<String>始终是同步或阻塞方法,因为无法等待异步或外部求值的任何所需结果来构造最终结果。
异步方法必须返回一个Future或类似类型的 Promise 对象,该对象允许它们在计算实际结果之前返回。这就要求调用者能够处理这种结果。当调用者必须将完整构造的结果返回给调用者时,它会让您回到第一个位置,因为它再次需要阻塞等待。
因此,这种传统的异步处理需要将所有处理步骤实现为异步操作,链接回调以将实际计算推迟到输入可用时。
\n虚拟线程的要点在于它们根本不需要您编写这种传统的异步方法。您可以以同步方式编写操作。继续以你为例,
\nList<String> straightForward() throws IOException {\n try(InputStream bigInputStream = getResponse()) {\n return deserialize(bigInputStream);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n它\xe2\x80\x99是调用者\xe2\x80\x99的责任在虚拟线程中调用您的代码,以获得好处。或者,也许\xe2\x80\x99s 更好的说法是\xe2\x80\x99s 调用者\xe2\x80\x99s 选择仅同步或在虚拟线程中使用你的方法。但调用者也可能以普通同步方式使用您的方法,但调用者将调用安排在虚拟线程中。
\n在最好的情况下,99% 的代码不处理线程或异步 API,而是直接以同步方式编写。只有剩下的 1% 必须在虚拟线程中安排调用,例如 Web 服务器为每个请求创建一个虚拟线程等。
\n| 归档时间: |
|
| 查看次数: |
616 次 |
| 最近记录: |