web-dev-qa-db-ja.com

OkHttpClientを並行して呼び出すことはスレッドセーフですか?

同時に実行されるいくつかのスレッドがあり、それらのいくつかはインターネットからデータを要求する必要があります。 OkHttpClientシングルトンへのアクセスの同期に注意する必要がありますか?

例えば、

スレッド1:

...
Request request = new Request.Builder()
    .url("http://hell.com/siners.txt")
    .build();

client.newCall(request).enqueue(new Callback() {
  @Override public void onFailure(Call call, IOException e) {
    e.printStackTrace();
  }

  @Override public void onResponse(Call call, Response response) throws IOException {
    try (ResponseBody responseBody = response.body()) {
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
      // Some work in Thread1
    }
  }

スレッド2:

...
Request request = new Request.Builder()
    .url("http://hell.com/slutList.txt")
    .build();

client.newCall(request).enqueue(new Callback() {
  @Override public void onFailure(Call call, IOException e) {
    e.printStackTrace();
  }

  @Override public void onResponse(Call call, Response response) throws IOException {
    try (ResponseBody responseBody = response.body()) {
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
      // Some work in Thread2
    }
  }

NewCall()。enque()またはnewCall()。execute()を同時に実行すると、潜在的に危険ですか?

21
Dmitrii Demenev

あなたは非常に良い質問をしました、私に全体論を説明させてください。 OkHttpに対して開かれたgithubの問題に基づくと、私の要約はこれです。

質問:複数の接続を作成するには、OkHttpClientの単一のインスタンスを再利用する必要があると思います。 OkHttpClientスレッドは安全ですか?そうでない場合、OkHttpClient.open()スレッドは安全ですか?

回答:はい。シングルトンとして扱われるように設計されています。単一のインスタンスを使用することで、共有の応答キャッシュ、スレッドプール、接続の再利用などが可能になります。間違いなくこれを実行してください!

質問:スレッドセーフについてはどうですか? OkHttpClientはスレッドセーフですか、それとも少なくともopen()関数ですか?

回答:はい

結論:

OkHttpClientsを共有する必要があります

OkHttpは、単一のOkHttpClientインスタンスを作成し、それをすべてのHTTP呼び出しに再利用する場合に最適に機能します。これは、各クライアントが独自の接続プールとスレッドプールを保持しているためです。接続とスレッドを再利用すると、待ち時間が短縮され、メモリが節約されます。逆に、リクエストごとにクライアントを作成すると、アイドルプールのリソースが浪費されます。

19
Remario