オープンソース プロジェクトのスレッド プールの使用を検討する

Java 開発としてのスレッド プールの使用は避けられないハードルです. スレッド プールを正しく使用する方法は、すべての開発が直面する問題です. 今日は、オープン ソース プロジェクトからトップ オープン ソース プロジェクトでスレッド プールがどのように使用されているかを見ていきます. . 私が最近参加したオープン ソース プロジェクトである RocketMQ の例を取り上げ、仕事で遭遇したいくつかの悪い習慣を組み合わせて、スレッド プールの使用について説明しましょう。次の側面から:

1.スレッドプールの作成

まずはRocketMQのスレッド作成BrokerController#initializeResources方法。以下に示すように:

一見、カスタムスレッドプールのように見えますが、ソースコードを見ると、BrokerFixedThreadPoolExecutor実際にThreadPoolExecutorますThreadPoolExecutor上記のスレッド プールの作成を分析すると、次の特徴が見つかります。

  • スレッドプールは名前で設定されます (推奨設定)

    なぜ名前を設定する必要があるのですか? 主な理由は、問題をトラブルシューティングするときに、どのスレッド プールによって実行されたどのコード フラグメントに問題があるかを知ることです。ThreadPoolExecutor のデフォルト名を使用するように名前を設定すると、トラブルシューティング時にどのスレッド プールかわかりません。

  • スレッド プール内のスレッド数を設定する

    ここで、このスレッドプールのスレッドを拡張する必要があるかどうかは、コアスレッドの数と最大スレッド数によって判断されます.たとえば、コアスレッドの数が10で、スレッドプールの最大数は10です. 100. その後、スレッドプールは動作中にコアスレッドの数を超えた後も継続します. タスクの実行を満たすためにスレッドを作成します. 一般的に、RocketMQ のコア スレッド プールと最大スレッド プールは同じサイズ、つまり固定サイズのスレッド プールに設定されていることがわかります。

  • タスク キューの設定容量をカスタマイズする (推奨設定)

    多くは RocketMQLinkedBlockingQueueで使用され、キューの容量を設定します。重要: キューの選択は個々のニーズに基づいていますが、キューに適切な容量を設定してください。容量を設定しない場合、デフォルトの容量は ですInteger.MAX_VALUE。これにより、タスク拒否ポリシーをトリガーする前に、メモリ不足によるサービスのダウンタイムが大幅に発生する可能性があります。

  • タスク拒否ポリシーの選択

    タスク拒否戦略の選択 一般に、JDK ThreadPoolExecutor のデフォルトの戦略を使用できますが、特別な要件がある場合、ユーザーは戦略をカスタマイズできます。

上記は、RocketMQ オープン ソース プロジェクトから見たスレッド プールの作成です。実際、多くの人はExecutorscreate。詳細については、記事「スレッド プール分析の作成に Executors を使用することが推奨されない理由」を参照してください。著者は、この記事で分析を行います。

2.スレッドプールの使用

RocketMQ のソース コードを調べた人は、RocketMQ に多数のスレッド プールがあることに気付くでしょう。多くの人は、すべてのタスクを完了するために 1 つのスレッド プールを使用しないのはなぜだろうかと疑問に思うでしょう。著者の仕事は、主に次の理由によるものです。

2.1 統一の原則

統一の原則を理解するには?つまり、スレッド プールはタスク処理のクラスを実行する必要があります。BrokerController#initializeResourcesのコードから、さまざまなタスクがさまざまなスレッド プールを使用して処理されていることがわかります。これを行う利点:

  • スレッド実行問題のトレースバックは便利であるが、スレッドプールの実行でエラーが発生した場合、エラースタックに従って単一性をトレースバックしやすくする必要がある。すべてのタスクがスレッド プールを使用して実行されている場合、スレッド プール名ではどのタスクに問題があるかわかりません。
  • キューのサイズをより適切に評価する機能
  • スレッド プールの実行中に問題が発生した場合、スレッド プールのシャットダウンまたはその他の問題は、1 つのタイプのタスクのみに影響し、すべてのタスクには影響しません。

2.2 適切な梱包

スレッド プールを適切にカプセル化すると、セキュリティを満たしながらコードをより洗練されたものにすることができます。これが上記のセマンティクスです。

3. スレッドプールの不適切な使用

筆者の前回の記事「Javaスレッドプールを不適切に使用するとどうなるか - 本番環境のケース」では、Controllerによって呼び出されるメソッド内にスレッドプールを作成し、非同期タスクを実行するという企業の本番環境ケースを紹介しました。この場合、毎回スレッド プールが作成され、スレッド プールは破棄されないため、メソッドが呼び出されるたびに、少なくとも 1 つのスレッドが作成されます。メソッドが 1000 回呼び出されると、1000 個のスレッドが作成されます。

@Service
@Slf4j
public class AccountAuthServiceImpl implements AccountAuthService {
     //省略了部分代码

      //功能:将两个系统账号进行绑定
      @Override
      public boolean bindUser(Long hrsAccountId, Long hmcAccountId){

        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*2);
        Future<Boolean> hrsExt = executorService.submit(new Callable<Boolean>() {

            @Override
            public Boolean call() throws Exception {
                //查询hrsAccountId是否存在
                return true;
            }
        });
        Future<Boolean> hmcExt = executorService.submit(new Callable<Boolean>() {

            @Override
            public Boolean call() throws Exception {
                //查询hmcAccountId是否存在
                return true;
            }
        });
        try {
            return hrsExt.get(3, TimeUnit.SECONDS) & hmcExt.get(3, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return false;
    }
}

4. まとめ

  • スレッド プールとスレッドは、問題が発生したときにトラブルシューティングを容易にするために、開発者になじみのある名前で設定する必要があります. これは、他のプロジェクトや Java のコマンドで見つけることができます. スレッドの命名は非常に重要なステップです. Java はデフォルト名を提供しますが、トラブルシューティングではカスタム名が特に重要です
  • スレッド プールのタスク キュー容量を設定する必要があります。そうしないと、メモリの消費やサービスのダウンタイムが発生する可能性があります
  • スレッドプールの作成はビジネスメソッドで作成できません

おすすめ

転載: blog.csdn.net/shy111111111/article/details/127472681