私は、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
クラス5000 times
のTimeoutThreadExample
メソッドを順番に呼び出します-
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
メソッドを1つずつ順番に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;
}
}
あなたの質問を理解できなかった場合は私を修正してください。前のものと非常に似ているようです 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
を使用して接続を作成することに注意してください。
私はマルチスレッドセーフシングルトンを持っています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
の代わりにorg.springframework.web.client.RestTemplate
http://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
RestTemplate
一度構築するとスレッドセーフになります 。したがって、1つのインスタンスを構築し、すべてのタスクで共有できます。各タスクから構築コストを排除し、ガベージコレクターの負荷を軽減するため、これははるかに効率的です。