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

我正在处理一个项目,其中我需要对正在运行的服务器进行HTTP URL调用,该服务器将响应作为JSON字符串返回。Restful Service

下面是我的主要代码,它使用和futurecallables -

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;
    }
}

下面是我的类,它实现了接口并使用...TaskCallableRestTemplate

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;
    }
}

现在我在另一个类中有下面的代码,它按顺序调用类中的方法 -DemoTestgetDataTimeoutThreadExample5000 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
        }
    }
}       

所以我的问题是,在我的这里应该是静态的,好像我看对了一样,我正在为每个请求重新创建整个连接池,我想这不是正确的方式。RestTemplateTask classRestTemplate

注意:如果我将 RestTemplate 设置为静态,那么在测量性能的类中注释掉第 1 行和第 2 行后,我看到与非静态相比,端到端的性能更好。RestTemplateDemoTest

一般来说,在多线程环境中使用的正确方法是什么?目前,我正在逐个按顺序调用方法 5000 次,但有些客户会以多线程方式调用它,因此需要知道在多线程环境中使用 RestTemplate 的最佳方式是什么。RestTemplategetData

可能是在 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;
    }
}

答案 1

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

在那里,我们确定这是线程安全的。因此,没有理由不分享它,只要它有意义,即。无论您以相同的方式使用它。您的示例似乎是执行此操作的理想之选。RestTemplate

如前所述,为每个实例重新创建一个新实例是浪费的。RestTemplateTask

我会创建 in 并将其作为构造函数参数传递给 。RestTemplateTimeoutThreadExampleTask

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;
    }
}

这样,您就可以在所有对象之间共享实例。RestTemplateTask

请注意,用于创建其连接。RestTemplateSimpleClientHttpRequestFactory


答案 2

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

请注意,我正在使用 ,并引用了我省略的oauth资源内容,因为它不相关。而不是一个,你可以很容易地使用 http://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.htmlOAuthRestTemplatemyResourceOAuthRestTemplateorg.springframework.web.client.RestTemplate


推荐