我正在开发一个项目,我需要对运行Restful Service
的服务器进行HTTP URL调用,该服务器将响应作为JSON字符串返回。
以下是我使用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;
}
}
以下是我的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;
}
}
现在我在另一个类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
}
}
}
所以我的问题是我的RestTemplate
中Task class
应该是静态的,就像我正确看到它一样,我正在为RestTemplate
中的每个请求重新创建整个连接池正确的方式,我猜..
注意:如果我将RestTemplate设为静态,那么在注释RestTemplate
类中的line1和line2之后,与非静态DemoTest
相比,我看到端到端的性能更好衡量绩效的方法。
一般来说,在多线程环境中使用RestTemplate
的正确方法是什么?目前我按顺序调用getData
方法5000次,但有些客户会以多线程方式调用它,所以需要知道在多线程环境中使用RestTemplate的最佳方法是什么。
可能是在RestTemplate构造函数中使用ConnectionFactory吗?有什么想法吗?
更新: -
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;
}
}
低于我的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;
}
}
答案 0 :(得分:17)
如果我不明白你的问题,请纠正我。它似乎与前一个here非常相似。
在那里,我们确定RestTemplate
是线程安全的。因此没有理由不在任何有意义的地方分享它,即。无论你以何种方式使用它。
你的例子似乎是完美的地方。
正如您所说,为每个RestTemplate
实例重新创建Task
的新实例是浪费。
我会在RestTemplate
中创建TimeoutThreadExample
并将其作为构造函数参数传递给Task
。
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;
}
}
这样您就可以在所有RestTemplate
个对象之间共享Task
实例。
请注意,RestTemplate
使用SimpleClientHttpRequestFactory
来创建其连接。
答案 1 :(得分:4)
我在春天有这样的多线程安全单例REST模板:
<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>
请注意我使用的是OAuthRestTemplate
,myResource
指的是我省略的oauth资源,因为它不相关。您可以轻松使用OAuthRestTemplate
http://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
org.springframework.web.client.RestTemplate
答案 2 :(得分:1)
NULL
is thread safe once constructed,因此您可以构建一个实例并让所有任务共享它。这样会更有效率,因为您可以消除每项任务的构建成本,并减少垃圾收集器的负载。