gpt4 book ai didi

java - 使用带有线程超时功能的ExecutorService如何提高性能?

转载 作者:行者123 更新时间:2023-12-02 11:07:34 25 4
gpt4 key购买 nike

我不是多线程专家,但我发现我当前使用 ExecutorService 的代码存在一些性能问题。

我正在开发一个项目,其中我需要对我的服务器进行 HTTP URL 调用,如果响应时间过长,则使调用超时。目前它正在返回简单的 JSON 字符串..

我目前的要求是10 毫秒。在10 ms内它应该能够从服务器取回数据。我猜想这是可能的,因为它只是对同一数据中心内的服务器的 HTTP 调用。

我的客户端程序和实际服务器位于同一数据中心内,它们之间的 ping 时间延迟为 0.5 毫秒,因此它应该是可行的。

我使用 RestTemplate 来进行 URL 调用。

下面是我为我编写的代码,它使用 ExecutorServiceCallables -

public class URLTest {

private ExecutorService executor = Executors.newFixedThreadPool(10);

public String getData() {
Future<String> future = executor.submit(new Task());
String response = null;

try {
System.out.println("Started..");
response = future.get(100, TimeUnit.MILLISECONDS);
System.out.println("Finished!");
} catch (TimeoutException e) {
System.out.println("Terminated!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

return response;
}
}

下面是我的任务类,它实现了 Callable 接口(interface) -

class Task implements Callable<String> {

private RestTemplate restTemplate = new RestTemplate();

public String call() throws Exception {
// TimerTest timer = TimerTest.getInstance(); // line 3
String response = restTemplate.getForObject(url, String.class);
// timer.getDuration(); // line 4

return response;

}
}

下面是我在另一个类DemoTest中的代码,它调用URLTest类中的getData方法500次并测量其端到端的第 95 个百分位数 -

public class DemoTest { 
public static void main(String[] args) {

URLTest bc = new URLTest();

// little bit warmup
for (int i = 0; i <= 500; i++) {
bc.getData();
}

for (int i = 0; i <= 500; i++) {
TimerTest timer = TimerTest.getInstance(); // line 1
bc.getData();
timer.getDuration(); // line 2
}

// this method prints out the 95th percentile
logPercentileInfo();

}
}

按照上面的代码,我总是看到 95% 为 14-15 ms (这对我的用例不利,因为它是端到端流,这就是我需要的测量)。

我很惊讶为什么? ExectuorFramework 是否会在这里添加所有延迟?可能是每个任务都被提交了,提交线程正在等待(通过future.get)直到任务完成..

我的主要目标是尽可能减少这里的延迟。我的用例很简单,对我的一台启用了超时功能的服务器进行 URL 调用,这意味着服务器是否需要花费大量时间来响应,然后使整个调用超时。客户将从那里的应用程序调用我们的代码,该应用程序也可以是多线程的。

有什么我遗漏的东西或者我需要使用一些其他风格的 ExecutorService 吗?我怎样才能提高我在这里的表现?任何建议都会有很大帮助..

任何示例将不胜感激..我正在阅读有关ExecutorCompletionService的内容,不确定我是否应该使用这个或其他东西..

最佳答案

根据您的观察,您在外部测量了 15 毫秒,但在内部仅测量了 3 毫秒,我敢打赌 RestTemplate 的构造会产生差异。这可以通过重构来解决。

请注意,RestTemplate 是一个重量级、线程安全的对象,并且设计为部署为应用程序范围的单例。您当前的代码严重违反了此意图。

<小时/>

如果您需要异步 HTTP 请求,那么您确实应该使用异步 HTTP 库,例如 AsyncHttpClient,它基于底层的 Netty,而 Netty 又基于 Java NIO。这意味着您不需要为每个未完成的 HTTP 请求占用一个线程。 AsyncHttpClient 还可以与 Futures 配合使用,因此您将拥有一个您习惯的 API。它还可以与回调一起使用,这是异步方法的首选。

但是,即使您保留当前的同步库,您至少也应该在 REST 客户端上配置一个超时,而不是让它自行运行。

关于java - 使用带有线程超时功能的ExecutorService如何提高性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21241036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com