Java 如何在多线程环境中高效使用 RestTemplate?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21242812/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use RestTemplate efficiently in Multithreaded environment?
提问by AKIWEB
I am working on a project in which I need to make a HTTP URL call to my server which is running Restful Service
which returns back the response as a JSON String.
我正在开发一个项目,在该项目中我需要对正在运行的服务器进行 HTTP URL 调用,该服务器Restful Service
将响应作为 JSON 字符串返回。
Below is my main code which is using the future
and callables
-
下面是我使用future
和的主要代码callables
-
public class TimeoutThreadExample {
private ExecutorService executor = Executors.newFixedThreadPool(10);
public String getData() {
Future<String> future = executor.submit(new Task());
String response = null;
try {
response = future.get(100, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return response;
}
}
Below is my Task
class which implements the Callable
interface and uses the RestTemplate
...
下面是我的Task
类,它实现了Callable
接口并使用了RestTemplate
...
class Task implements Callable<String> {
private RestTemplate restTemplate = new RestTemplate();
public String call() throws Exception {
String url = "some_url";
String response = restTemplate.getForObject(url, String.class);
return response;
}
}
And now I have below code in another class DemoTest
which calls the getData
method in TimeoutThreadExample
class 5000 times
sequentially -
现在我有下面的代码在另一大类DemoTest
它调用的getData
方法TimeoutThreadExample
类5000 times
顺序-
public class DemoTest {
public static void main(String[] args) {
TimeoutThreadExample bc = new TimeoutThreadExample();
for (int i = 0; i <= 5000; i++) {
// TimerTest timer = TimerTest.getInstance(); // line 1
bc.getData();
// timer.getDuration(); // line 2
}
}
}
So my question is should RestTemplate
be static here in my Task class
as if I see it correctly, I am recreating the whole connection pool for each request in RestTemplate
which is not the right way I guess..
所以我的问题应该RestTemplate
是静态的,Task class
就好像我没看错一样,我正在为每个请求重新创建整个连接池,RestTemplate
我猜这不是正确的方式。
NOTE:If I am making RestTemplate static, then I see better performance end to end as compared to non static RestTemplate
after commenting out line1 and line2 in DemoTest
class which measures the performance.
注意:如果我将 RestTemplate 设为静态,那么RestTemplate
在注释掉DemoTest
衡量性能的类中的line1 和 line2 之后,与非静态相比,我看到端到端的性能更好。
In general what is the right way to use RestTemplate
in Multithreading environment? Currently I am calling sequentially getData
method 5000 times one by one but some customer will call it in a multithreaded way so need to know what is the best way to have RestTemplate in a multithreaded environment..
一般来说,RestTemplate
在多线程环境中使用的正确方法是什么?目前我正在getData
一个接一个地调用顺序方法 5000 次,但有些客户会以多线程方式调用它,所以需要知道在多线程环境中使用 RestTemplate 的最佳方法是什么..
May be to use ConnectionFactory in the RestTemplate constructor? Any thoughts?
可能是在 RestTemplate 构造函数中使用 ConnectionFactory 吗?有什么想法吗?
UPDATE:-
更新:-
public class TimeoutThreadExample {
private ExecutorService executor = Executors.newFixedThreadPool(10);
private RestTemplate restTemplate = new RestTemplate();
public String getData() {
Future<String> future = executor.submit(new Task(restTemplate));
String response = null;
try {
response = future.get(100, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return response;
}
}
And below my TaskClass
-
在我的下面TaskClass
-
class Task implements Callable<String> {
private RestTemplate restTemplate;
public Task(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public String call() throws Exception {
String url = "some_url";
String response = restTemplate.getForObject(url, String.class);
return response;
}
}
采纳答案by Sotirios Delimanolis
Correct me if I didn't understand your question. It seems very similar to the previous one here.
如果我不明白你的问题,请纠正我。它似乎与这里的前一个非常相似。
There, we determined that RestTemplate
is thread-safe. There is therefore no reason not to share it wherever it makes sense to, ie. wherever you are using it in the same way.
Your example seems like the perfect place to do so.
在那里,我们确定这RestTemplate
是线程安全的。因此,没有理由不在任何有意义的地方共享它,即。无论您在哪里都以相同的方式使用它。您的示例似乎是这样做的理想场所。
As you stated, recreating a new instance of RestTemplate
for each Task
instance is wasteful.
正如您所说,RestTemplate
为每个Task
实例重新创建一个新实例是浪费的。
I would create the RestTemplate
in TimeoutThreadExample
and pass it to the Task
as a constructor argument.
我会创建RestTemplate
inTimeoutThreadExample
并将其Task
作为构造函数参数传递给 the 。
class Task implements Callable<String> {
private RestTemplate restTemplate;
public Task(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public String call() throws Exception {
String url = "some_url";
String response = restTemplate.getForObject(url, String.class);
return response;
}
}
This way you share the RestTemplate
instance between all your Task
objects.
这样您就可以RestTemplate
在所有Task
对象之间共享实例。
Note that RestTemplate
uses SimpleClientHttpRequestFactory
to create its connections.
请注意,RestTemplate
用于SimpleClientHttpRequestFactory
创建其连接。
回答by Taylor
I have my multi-thread-safe singleton REST template wired like this in spring:
我的多线程安全单例 REST 模板在 spring 中是这样连接的:
<bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams" id="httpConnectionManagerParams">
<property name="connectionTimeout" value="10000"/>
</bean>
<bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager" id="httpConnectionManager">
<property name="params" ref="httpConnectionManagerParams"/>
</bean>
<bean class="org.apache.commons.httpclient.params.HttpClientParams" id="httpClientParams">
<property name="authenticationPreemptive" value="true"/>
<property name="soTimeout" value="10000"/>
</bean>
<bean class="org.apache.commons.httpclient.HttpClient" id="httpClient">
<constructor-arg ref="httpClientParams"/>
<constructor-arg ref="httpConnectionManager"/>
</bean>
<bean class="org.springframework.http.client.CommonsClientHttpRequestFactory" id="httpClientFactory">
<constructor-arg ref="httpClient"/>
</bean>
<bean class="org.springframework.security.oauth.consumer.client.OAuthRestTemplate" id="restTemplate">
<constructor-arg ref="httpClientFactory"/>
<constructor-arg ref="myResource"/>
<property name="messageConverters">
<list>
<ref bean="marshallingHttpMessageConverter"/>
</list>
</property>
</bean>
Please note I'm using an OAuthRestTemplate
, and myResource
refers to the oauth resource stuff which I've omitted as it's not relevant. Instead of an OAuthRestTemplate
you could just as easily use a org.springframework.web.client.RestTemplate
http://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
请注意,我使用的是OAuthRestTemplate
, 并myResource
指的是我省略的 oauth 资源内容,因为它不相关。而不是OAuthRestTemplate
你可以很容易地使用org.springframework.web.client.RestTemplate
http://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
回答by Raedwald
A RestTemplate
is thread safe once constructed, so you can construct one instance and have all your tasks share it. That will be much more efficient, because you eliminate the construction cost from each task, and reduce the load on the garbage collector.
ARestTemplate
一经构建就是线程安全的,因此您可以构建一个实例并让您的所有任务共享它。这会更有效率,因为您消除了每个任务的构建成本,并减少了垃圾收集器的负载。