gpt4 book ai didi

java - 代码在 Java 线程内花费更长的时间

转载 作者:行者123 更新时间:2023-11-30 10:31:13 25 4
gpt4 key购买 nike

我需要尽快执行最多 10 个 HTTP Post 操作。所有的帖子都到同一个目的地,为了简化事情,你可以假设他们现在都在做同样的操作。每一毫秒都很重要。在没有任何线程的情况下,作为主代码的一部分执行单个 HTTP post 操作通常需要 50 毫秒:

long start = System.currentTimeMillis( );
response = httpClient.execute(httppost, context);
long end = System.currentTimeMillis( );
long diff = end - start;
System.out.println(Thread.currentThread().getName() + ": Difference is: " + diff);

但是为了一次做几个,我为每个 HTTP post 操作创建一个线程,并向每个线程传递相同的 HttpClient 对象,并使用 PoolingHttpClientConnectionManager 完成:

protected HttpClient createHttpClient() {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(20);
cm.setDefaultMaxPerRoute(24);
RequestConfig.Builder requestBuilder = RequestConfig.custom();
requestBuilder = requestBuilder.setConnectTimeout(5000);
requestBuilder = requestBuilder.setSocketTimeout(5000);

HttpClientBuilder builder = HttpClientBuilder.create();
builder.setDefaultRequestConfig(requestBuilder.build());
builder.setConnectionManager(cm);

return builder.build();
}

CloseableHttpClient httpClient = (CloseableHttpClient) createHttpClient();
HttpParams httpParams = new DefaultHttpClient().getParams();

Runnable threadJob = new MyRunnable(httpClient, post);

Thread one = new Thread(threadJob);
Thread two = new Thread(threadJob);
Thread three = new Thread(threadJob);
Thread four = new Thread(threadJob);
Thread five = new Thread(threadJob);
Thread six = new Thread(threadJob);
Thread seven = new Thread(threadJob);
Thread eight = new Thread(threadJob);
Thread nine = new Thread(threadJob);
Thread ten = new Thread(threadJob);
one.start();
two.start();
three.start();
four.start();
five.start();
six.start();
seven.start();
eight.start();
nine.start();
ten.start();

在 MyRunnable 类中,同样的 50 毫秒操作似乎需要更长的时间。请注意,我没有在我的指标中包括创建线程等的开销——我希望这会增加总时间,但让我困惑的是为什么相同的 httpclient.execute() 操作在内部需要更长的时间一个线程,而不是在它之外。在 MyRunnable 的 run() 方法中:

long start = System.currentTimeMillis( );
response = httpClient.execute(httppost, context);
long end = System.currentTimeMillis( );
long diff = end - start;
System.out.println(Thread.currentThread().getName() + ": Difference is: " + diff);

我的机器有 2 个内核,但有 4 个逻辑处理器。
如果我执行 4 个线程,记录的时间通常是这样的:

58 毫秒155毫秒160毫秒179毫秒

“n”个线程始终如此——第一个完成的线程注册的时间略长于 50 毫秒的“标准”时间,然后其余所有线程都需要大约 3 倍的时间。 10 个线程的另一个典型结果集:

52 毫秒156毫秒156毫秒160毫秒156毫秒161毫秒175毫秒158毫秒176毫秒178毫秒

问题:

  1. 我的“之前和之后”记录方法是否是需要多长时间的可靠方法?

  2. 这是在线程内执行 http post 操作时的方式,还是我可以做些什么来降低平均时间? (除了购买更强大的机器)。

最佳答案

Within the MyRunnable class, the same 50ms operation seems to take a good bit longer. Note I am not including the overhead of creating the thread etc in my metrics – I expect that to add to the overall time, but what’s perplexing me is why the same httpclient.execute() operation takes longer inside a thread, than it would be outside it.

您首先需要了解多线程的工作原理。这并不是说当您创建并启动一个 Thread 时它只是并行运行,而是等待轮到它执行 run() 方法(当 number_of_threads > 处理器)。

换句话说,当有一个线程在运行时(或 number_of_threads < 处理器),您不会看到任何开销,因为处理器将空闲并简单地执行您的请求。现在,转到另一种情况,您运行的线程多于可用的处理器,显然,线程需要一些时间才能轮到它们,这称为上下文切换开销,因此您会注意到一些差异响应时间明显。

您可能有兴趣了解线程如何优先轮到执行run() 方法,您可以查看here对此。简单来说,这实际上是由 JVM 内部的 Thread Scheduler 处理的。

此外,我建议您阅读 here并了解多线程工作原理的基础知识。

Is my ‘before and after’ logging method a reliable method of how long it takes?

您的 System.currentTimeMillis() 没问题,或者您也可以使用 Instant来自 Java8 的 API。

Is this just the way it is when executing an http post operation inside a thread, or is there anything I can do to bring the average time down? (short of buying a more powerful machine)?

我建议不要自己手动创建和维护线程,而是使用 ExecutorService类似于 ExecutorService.newFixedThreadPool(10) 的 API。这可能不会减少平均时间,而是会帮助您将线程作为一个池进行正确管理。

关于java - 代码在 Java 线程内花费更长的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43304709/

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