当前位置: 首页 > 知识库问答 >
问题:

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

湛钊
2023-03-14

我正在做一个项目,在这个项目中,我需要对运行Restful服务的服务器进行一个httpurl调用,该服务以JSON字符串的形式返回响应。

下面是我的主要代码,它使用的是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;
    }
}

下面是我的任务类,它实现了Callable接口,并使用了RestTem板...

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

现在我在另一个类demost中有下面的代码,它依次调用TimeoutThreadExample5000次中的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
        }
    }
}       

因此,我的问题是,在我的任务类中,restemplate是否应该是静态的,就好像我没有看错一样,我正在为restemplate中的每个请求重新创建整个连接池,我想这不是正确的方式。。

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

一般来说,在多线程环境中使用RestTem板的正确方法是什么?目前,我正在一个接一个地调用顺序getData方法5000次,但有些客户会以多线程的方式调用它,所以需要知道什么是在多线程环境中最好的方法...

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

共有3个答案

顾磊
2023-03-14

RestTemplate一旦构建,它是线程安全的,因此您可以构建一个实例并让所有任务共享它。这将更有效率,因为您消除了每个任务的构建成本,并减少了垃圾收集器的负载。

夏朝
2023-03-14

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

请注意,我使用的是OAuthRestTemboard,而myResources指的是oauth资源,我忽略了它,因为它不相关。代替OAuthRestTem板,您可以同样轻松地使用org.springframework.web.client.RestTem板http://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

巢星纬
2023-03-14

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

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

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

我将在TimeoutThread示例中创建RestTem板,并将其作为构造函数参数传递给任务

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

通过这种方式,您可以在所有任务对象之间共享restemplate实例。

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

 类似资料:
  • 问题内容: 我正在开发一个项目,在该项目中,我需要对正在运行的服务器进行HTTP URL调用,该服务器将响应作为JSON字符串返回。 下面是我的主要代码,它使用和- 下面是我的类,它实现接口并使用… 现在我有下面的代码在另一大类它调用的方法类顺序- 所以我的问题是在这里应该是静态的,就像我正确看到的一样,我正在为每个请求重新创建整个连接池,而我猜这不是正确的方法。 注意: 如果我将RestTemp

  • 我正在使用多线程执行插入操作。我使用了带注释的方法,我的方法是注释。但我无法执行插入操作,导致出现以下异常。 异常线程"Thread-21"javax.persistence.Transaction必需异常:在org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96)在sun.reflect.Native

  • 问题内容: 典型的(对于x86-64平台和Linux OS)是在开始时幼稚地锁定互斥锁并在完成后将其释放,还是以更巧妙的方式将互斥锁锁定在更精细的级别,从而减少了锁争用?如果确实采用第二种方法,那么该如何做? 问题答案: 经营多个分配 场所 。每个竞技场都有自己的锁。当线程需要分配内存时,选择一个竞技场,将其锁定,然后从中分配内存。 选择竞技场的机制有些复杂,旨在减少锁争用: 考虑到这一点,基本上

  • 关于Spring WebClient我有一个问题 在我的应用程序中,我需要做许多类似的API调用,有时我需要更改调用中的头(身份验证令牌)。所以问题来了,在这两个选择中,什么更好: > 为所有传入的MyService.class请求创建一个WebClient,方法是将其设置为字段,如下代码所示: 谢谢你。

  • 我正在使用作为我的一个库中的。我不确定我是否在多线程环境中正确地使用它,因为我的库在多线程环境中会在非常大的负载下使用,所以它必须非常快。 下面是我的DataClient类: 这就是我要打电话获取数据的方式: 现在我的问题是--我不确定我是否正确地将与一起使用。这里是否需要以及? 我的主要目标是在多线程环境中高效地使用。因为我的库将在非常大的负荷下使用,所以它必须非常快。在重载下,我看到了大量的T

  • 问题内容: 一段时间以来,我一直在多线程环境中使用HttpClient。对于每个线程,当它启动连接时,它将创建一个全新的HttpClient实例。 最近,我发现使用这种方法可能导致用户打开太多端口,并且大多数连接处于TIME_WAIT状态。 http://www.opensubscriber.com/message/commons-httpclient- dev@jakarta.apache.or