Java 如何在多线程环境中有效地使用RestTemplate?

Java 如何在多线程环境中有效地使用RestTemplate?,java,multithreading,static,connection-pooling,resttemplate,Java,Multithreading,Static,Connection Pooling,Resttemplate,我正在做一个项目,在这个项目中,我需要对运行Restful服务的服务器进行一个httpurl调用,该服务以JSON字符串的形式返回响应 下面是我的主要代码,它使用的是future和callables- public class TimeoutThreadExample { private ExecutorService executor = Executors.newFixedThreadPool(10); public String getData() {

我正在做一个项目,在这个项目中,我需要对运行
Restful服务的服务器进行一个httpurl调用,该服务以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;
    }
}
现在我在另一个类
demost
中有下面的代码,它依次调用
TimeoutThreadExample
5000次
中的
getData
方法-

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
        }
    }
}       
在我的
任务类下

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 RestTemplate;
公共任务(RestTemplate RestTemplate){
this.restTemplate=restTemplate;
}
公共字符串调用()引发异常{
String url=“some_url”;
String response=restTemplate.getForObject(url,String.class);
返回响应;
}
}

如果我不明白你的问题,请纠正我。它似乎与前一个非常相似

在这里,我们确定
restemplate
是线程安全的。因此,没有理由不在任何有意义的地方分享它,例如,无论你以同样的方式使用它的地方。 你的例子似乎是这样做的最佳场所

如前所述,为每个
任务
实例重新创建
restemplate
的新实例是浪费

我将在
TimeoutThreadExample
中创建
restemplate
,并将其作为构造函数参数传递给
任务

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 RestTemplate;
公共任务(RestTemplate RestTemplate){
this.restTemplate=restTemplate;
}
公共字符串调用()引发异常{
String url=“some_url”;
String response=restTemplate.getForObject(url,String.class);
返回响应;
}
}
通过这种方式,您可以在所有
任务
对象之间共享
restemplate
实例


请注意,
RestTemplate
使用
SimpleClientHttpRequestFactory
创建其连接。

我的多线程安全单例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>


请注意,我使用的是一个
OAuthRestTemplate
,而
myResource
指的是我忽略的oauth资源内容,因为它不相关。您可以轻松地使用
org.springframework.web.client.restemplate
a
restemplate
,而不是
OAuthRestTemplate
,这样您就可以构建一个实例并让所有任务共享它。这将更有效率,因为您消除了每个任务的构建成本,并减少了垃圾收集器的负载

我明白了。。简言之,它们都是一样的。。在任务类中制作静态文件?或者通过传递对象来使用DI?RestTemplate是线程安全的,但您还必须确保下面的http连接管理器是线程安全的,例如使用
org.apache.commons.httpclient.multi-threadedHttpConnectionManager
(请注意,我使用的是commons httpclient 3.1,因此这可能不适用于其他版本)另一个接近的副本:。显然OP在这里有两个身份,从这个意义上说,是的。顺便说一句,我真诚地建议您研究一下URLConnection的实现——我认为您会改变“更难使用”的想法:)可能的重复
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;
    }
}
<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>