ホームページ  >  記事  >  Java でシングルトン Bean スレッドを安全にし、パフォーマンスを向上させるにはどうすればよいですか?

Java でシングルトン Bean スレッドを安全にし、パフォーマンスを向上させるにはどうすればよいですか?

王林
王林転載
2024-02-09 09:00:20982ブラウズ

Java 開発では、シングルトン パターンは、クラスのインスタンス オブジェクトが 1 つだけであることを保証するために一般的に使用される設計パターンです。ただし、マルチスレッド環境では、シングルトン パターンを使用するとスレッド セーフティの問題が発生し、プログラムのパフォーマンスと正確性に影響を与える可能性があります。では、Java でシングルトン Bean スレッドを安全にし、パフォーマンスを向上させるにはどうすればよいでしょうか? PHPエディターのYuzaiが以下の点について紹介し、回答します。

質問内容

以下のコードを複数のユーザーでテストしようとしています。ただし、クラスは Spring によって管理されるシングルトンであるため、作成されるオブジェクトは 1 つだけであり、複数のスレッドが同じオブジェクトにアクセスしようとします。

出力文字列に一貫性がないため。 applogger メソッドで synchronized キーワードを使用して、この問題を解決してみてください。期待どおりに機能しています。しかし、パフォーマンスに関しては妥協する必要があります。

マルチスレッド環境でシングルトン Bean を処理し、インスタンス変数 (文字列ビルダー) の変更を通じてパフォーマンスを向上させるにはどうすればよいですか?

コードを編集し、aggregatelogger メソッドを追加します。このメソッドは、クラス レベルで宣言された既存の stringbuilder に文字列を集約するため、stringbuilder には applogger メソッドと aggregatelogger メソッドからの集約されたログが含まれます。

@Aspect
    @Slf4j
    @Component
    public class A{
     private StringBuilder builder = new StringBuilder();
     public StringBuilder getSb(){
     return builder;
     }
     public void appendToSb(String s){
     builder.append(s);
     }

    @Around("@annotation(execTimeLogger)")
    public Object appLogger(ProceedingJointPoint pjp){
     long startTime = xxx;
     Object object = pjp.proceed();
     long endTime = xxx;
     String str = "Hello";
     appendToSb(str);
    return object;
    }

    @Around("@annotation(logger)")
    public Object aggregateLogger(ProceedingJointPoint pjp){
     long startTime = xxx;
     Object object = pjp.proceed();
     long endTime = xxx;
     String str = "World";
     appendToSb(str);
     log.info(getSb().toString()); // o/p will be Aggregated Log 
     getSb().setLength(0);
    return object;
    }
    
}

解決策

あなたの設計は間違っています。率直なことを許してください。ログを記録する 1 つのビジネス トランザクション内でも、複数のスレッドで複数の操作を実行する複数のアプリケーション層が存在する場合があります。なぜこれらすべてを 1 つのログ メッセージに含める必要があるのでしょうか?通常、ある種の顧客 ID やトランザクション ID、または追跡して記録する論理エンティティを正確に識別するものを使用して、すべてのメッセージを記録します。ほとんどのログ フレームワークは、何らかの Mapped Diagnostic Context (MDC) を使用します。コンソールにログインするか、データベースにログインするか、Logstash や Graylog などのログ アグリゲータにログインするかに関係なく、関心のあるエンティティまたはトランザクションごとに検索、フィルタリング、集計して、対応するすべてのログ メッセージを見つけることができます。すべてを 1 つのログ メッセージにまとめる必要はありません。

もちろん、コア コードをログ ステートメントで汚染する代わりに、ログ記録の側面を活用することもできます。ロギングなどの横断的な問題を解決できることは、AOP の主な利点の 1 つです。しかし、それは正しく行うべきです。そのため、シングルトン アスペクトは MDC を使用するか、何らかのマッピングで独自の簿記を行います。ロギング フレームワークがすでに提供しているツールを使用し、アスペクトが最も得意とすること、つまり正しい結合ポイントをインターセプトすることに集中させることをお勧めします。

パフォーマンスも懸念事項の 1 つであるため、アプリケーションの速度と応答性を高めるために、非同期でログを記録するようにログ フレームワークを構成することをお勧めします。ファイルへのログ記録は、通常、コンソールへのログ記録よりも高速です。おそらく、この GitHub リポジトリ には、ここで説明する内容に加えて、興味深い Readme や JMH ベンチマークなど、興味深い情報が含まれています。もしあなたがドイツ語を話せるなら、私は数日前に この Heise.de ブログ に投稿しました。この記事のドイツ語の内容は基本的に英語の Readme と同じですが、ソースを提供したかっただけです。

とにかく、非同期ログを使用する場合、マルチスレッドのコンテキストではログ集約 ID がより重要になります。

以上がJava でシングルトン Bean スレッドを安全にし、パフォーマンスを向上させるにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。