ホームページ  >  記事  >  Java  >  Javaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法

Javaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法

王林
王林転載
2023-05-12 14:22:062419ブラウズ

マルチスレッド実行メソッドでサービス ビジネス クラスを直接呼び出す場合は注意が必要です。

Java マルチスレッド実行メソッドでサービス ビジネス クラスを使用すると、java.lang.NullPointerException 例外が発生します。これは、spring によって挿入されたビジネス クラスが null であるか、直接の新しいビジネス オブジェクトも null であることが原因です。

マルチスレッドではスレッドセーフのためインジェクションが防止されるため、サービスビジネスクラスを利用する場合は、ApplicationContextメソッドを使用してBeanメソッドを取得し、サービスクラスを取得する必要があります。

ApplicationContext クラスを取得するには、次のように ApplicationContextAware インターフェイスを実装する必要があります:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
 
public class ApplicationContextUtil implements ApplicationContextAware {
 
	private static ApplicationContext context;
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		this.context = context;
	}
	public static ApplicationContext getContext() {
		return context;
	}
}

次に、上記のメソッドを run メソッドで使用して、次のようにビジネス オブジェクトを作成します。

XXXServiceI xxxService = ApplicationContextUtil.getContext.getBean(XXXServiceI.class);

これで普通に使えます ビジネスクラスは終了です。

図は次のとおりです

Javaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法

Javaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法

Javaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法#マルチスレッドの知識ポイント

スレッドを開始する 4 つの方法

1. Thread クラスを継承して Thread の run メソッドを書き換え、run メソッド内で操作を実行し、start メソッドを使用してスレッドを開始します

Javaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法2. Runnable インターフェイスを継承し、run メソッドを実装し、run メソッドで操作を実行します。現在のクラスのインスタンス オブジェクトを渡して Thread インスタンスを作成し、次に呼び出す必要があります。スレッドを開始するための start メソッド

Javaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法3. Callable インターフェイスを実装し、call() メソッドを書き換えます。最初の 2 つのメソッドは応答を必要としないことに注意してください。ただし、Callable インターフェースを実装して call() メソッドを書き換えると、スレッドの応答を待つ必要があるため、他のスレッドが起動しているにもかかわらず 1 つのスレッドが実行され、標準とはみなされません。マルチスレッド。

Javaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法4. スレッド プール

Javaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法#@Aysnc アノテーションを使用してマルチスレッドを実装する

同じクラス、メソッド A はメソッド B を参照します。メソッド B に非同期 @Async アノテーションを追加しても効果はありません

追加された @Async メソッドと呼び出し元を同じクラスに置くことはできません

ユーザー スレッドとデーモン スレッドの違い

Java で作成されたスレッドは、デフォルトで新しい Thread (スレッド オブジェクト) などのユーザー スレッドを作成します。start

    Thread thread = new Thread();
    // 默认为false,都是用户线程
    thread.setDaemon(true); // 表示设置为守护线程
    thread.setDaemon(false); // 表示设置为用户线程

  • User thread

    : No 他のスレッドが死ぬと死ぬ スレッドが死ぬ状況は 2 つだけあり、1 つは動作中に例外が発生して終了する場合、もう 1 つはプログラムが正常に実行されてスレッドが死ぬ場合です

  • デーモン スレッド

    : ユーザー スレッドが終了すると終了します。ユーザー スレッドが終了すると、gc ガベージ コレクション スレッドなどのデーモン スレッドも終了します。ユーザー スレッドが存在する場合、gc は生きている必要があり、そうでない場合は役に立ちません。

  • スレッドの 6 つの状態

1. 新規: 初期状態、スレッドは作成され、start() は呼び出されません

2. 実行可能:実行ステータス。Java スレッドは、オペレーティング システムの準備完了と実行中の 2 つの状態を「実行中」と呼びます。

3. ブロック済み: ブロックされ、スレッドは待機状態になり、スレッドは CPU の使用を放棄します。何らかの理由

    ブロッキングのいくつかの状況:
  • A. ブロッキングを待機中: 実行中のスレッドが wait() を実行し、JVM が Put
  • #B. 同期ブロック: 実行中のスレッドがオブジェクトの同期ロックを取得するとき、同期ロックが他のスレッドによって占有されている場合、JVM は現在のC. その他のブロッキング: 実行中のスレッドが sleep()、join() を実行するか、IO リクエストを発行すると、JVM は現在のスレッドをブロッキングに設定します。 sleep() 実行後、join() スレッドは終了し、IO 処理後に再びスレッドが再開されます
  • 4. 待機中: 待機状態
  • 5。 timed_waiting: タイムアウト待機状態、タイムアウト後に自動的に Return

    6.terminated: 終了ステータス、現在のスレッドは実行を完了しました
Java ロックの再入可能性

Java の再入性メカニズムlock は次の問題を解決できます。コードに直接アクセスしてください:

 public class Demo1 {
    public synchronized void functionA(){
        System.out.println("iAmFunctionA");
        functionB();
    }
    public synchronized void functionB(){
        System.out.println("iAmFunctionB");
    }

Java にはアトミック性を強制する同期された内部ロック メカニズムが提供されていないと仮定します: functionA() と functionB() は両方とも同期メソッドです。 funcitonA() に入ると、このクラスのオブジェクト ロックを取得します。このロック「new Demo1()」は functionA() 内のメソッド functionB() を呼び出しますが、functionB() も同期されるため、スレッドはオブジェクト ロック (new Demo1()) を再度実行しますが、JVM はこのオブジェクトのロックを取得したと考えられ、再度取得できないため、functionB() メソッドを呼び出すことができず、デッドロックが発生します。

スレッド プールの 4 つの拒否戦略

スレッド プールのタスク キャッシュ キューがいっぱいで、スレッド プール内のスレッド数が MaximumPoolSize に達したとき、まだ到着しているタスクがある場合、タスク拒否戦略は次のようになります。通常、次の 4 つの戦略があります:

ThreadPoolExecutor.AbortPolicy: タスクを破棄し、RejectedExecutionException をスローします。

ThreadPoolExecutor.DiscardPolicy: タスクを破棄しますが、例外はスローしません。

ThreadPoolExecutor.DiscardOldestPolicy: キューの最前面のタスクを破棄し、拒否されたタスクを再送信します。

ThreadPoolExecutor.CallerRunsPolicy: 呼び出し側スレッドによって(タスクを送信したスレッド) タスクを処理します

sleep と wait の違い

  • sleep はスレッド内のメソッドですが、wait は Object 内のメソッドです

  • sleep メソッドはロックを解放しませんが、wait はロックを解放し、待機キューに追加されます

  • sleep は必要ありません覚醒する必要がありますが、wait は実行します

wait()、notify()、notifyAll() が Thread クラスではなくオブジェクト内にある理由

ロック レベルJava では、スレッド レベルではなくオブジェクト レベルであり、各オブジェクトにはスレッドを通じて取得されるロックがあります。 wait() メソッドがスレッド内にある場合、スレッドがどのロックを待機しているかは明らかではありません。

以上がJavaマルチスレッド実行メソッドでサービス・ビジネス・クラスを直接呼び出す方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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