この記事では、java に関する関連知識を提供します。主に、例外のキャプチャなど、サブスレッド タスクで例外が発生したときにメイン スレッド トランザクションをロールバックする方法に関する関連問題を紹介します。トランザクションのロールバックなどについて、以下で見ていきましょう。
## 推奨学習: 「
Java ビデオ チュートリアル 」
1. 質問する
メイン スレッドはタスクをスレッド プールに送信しました。このタスクの実行中に例外が発生した場合、メイン スレッドはどのように例外をキャッチしてトランザクションをロールバックできますか?
2. メイン スレッドとサブスレッド
最初に基本を見てみましょう。次の図は、2 つのスレッドがどのように実行されるかを示しています。
左の図は、メインスレッドがサブスレッドを開始した後、2 つのスレッドが互いに干渉することなく独立して実行されることを示しています。生と死は運命によって決まります。これからは、あなたと私は通行人! - 右図は、メインスレッドがサブスレッドを開始し、その後メインスレッドのプログラムロジックを実行し続け、あるノードでブロックすることでサブスレッドの実行結果を取得する様子を示しています。
-
#上記の問題について、2 番目の方法は、子スレッドの実行中に発生する例外をメインスレッドがキャプチャできるという問題を解決する必要があります。 。ここでインタビューの質問をする必要があります。スレッドを実装する 2 つのインターフェイス Callable と Runnable の違いです。
public interface Callable<v> {
V call() throws Exception;}</v>
ログイン後にコピー
public interface Runnable {
public abstract void run();}
ログイン後にコピー
call メソッドには戻り値があり、run メソッドには戻り値がないことがわかります。さらに、call メソッドは例外をスローできますが、run メソッドは例外をスローできません。明らかに、サブスレッドの実行結果や実行例外をキャプチャまたは知るには、Callable インターフェイスを介して実装する必要があります。
ここでは、ExpSubThread クラス (サブスレッド例外シミュレーション クラス) を作成し、Callable インターフェイスを実装し、あまり多くのアクションを実行せずに null ポインター例外を直接スローします。
public class ExpSubThread implements Callable {
@Override
public Object call() throws Exception {
throw new NullPointerException();
}}
ログイン後にコピー
3. スレッド プール
スレッド タスクに直面したとき、通常、事前に計画された n 個のスレッド リソースの集合であるスレッド プールを確立します。その利点は次のとおりです。
タスクを実行するとき、新しいスレッドは作成されませんが、スレッド プール内の既存のスレッド リソースが使用されます。タスクの実行が完了すると、スレッド リソースは破棄されず、スレッド プールに戻されます。したがって、スレッドの作成と破棄によって消費されるリソースがある程度節約され、スレッド リソースの再利用の目的が達成されます。 - スレッド プールのサイズには上限があるため、スレッド プールのもう 1 つの機能は、無制限のスレッドの作成を回避し、無制限のアプリケーション リソースによって引き起こされるシステム クラッシュを回避することです。
-
一般的に使用されるスレッド プールは 2 つあり、1 つは JDK に付属するもので、もう 1 つは Spring スレッド プールです。後者は Spring 環境でよく使用され、似ています。 。ここでは Spring API を使用してスレッド プールを構築します。
public ThreadPoolTaskExecutor getThreadPool(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(100); //线程池最大线程数
executor.setCorePoolSize(50);//线程池核心线程数
executor.setQueueCapacity(50);//任务队列的大小
executor.setThreadNamePrefix("test_"); //线程前缀名
executor.initialize(); //线程初始化
return executor;}
ログイン後にコピー
4. 例外キャプチャ
以下は私が書いたテストケースで、メインスレッドのプログラム実行フローを表しています
@Testvoid subThreadExceptionTest() {
try{
//新建子线程对象
ExpSubThread expSubThread = new ExpSubThread();
//构建线程池
ThreadPoolTaskExecutor executor = getThreadPool();
//提交子线程任务,submit方法
Future future = executor.submit(expSubThread);
//在这里可以做主线程的业务其他流程操作
//阻塞等待子线程的执行结果
Object obj = future.get();
}catch (Exception e){
e.printStackTrace();
//事务回滚
}}
ログイン後にコピー
ここで注意すべき点submit メソッドを使用して、サブスレッド タスクをスレッド プールに送信して実行します。 ThreadPoolTaskExecutor には、スレッド タスクを実行するための 2 つのメソッドがあります。1 つは実行メソッド、もう 1 つは送信メソッドです。
execute メソッドには戻り値がないため、タスクが正常に完了したかどうかを判断することはできません。対応するスレッド クラスは Runnable インターフェイスを実装します。 - submit メソッドには戻り値があり、Future を返し、対応するスレッド クラスは Callable インターフェイスを実装します。
-
Future.get() メソッドは、メインスレッドをブロックする目的を達成し、サブスレッドタスクの実行結果を判断できるようにします。 get メソッドは例外をスローできます。
V get() throws InterruptedException, ExecutionException;
ログイン後にコピー
下の図は、上記のテスト ケース プログラム
e.printStackTrace(); の効果です。この図から 2 つの例外がわかります。1 つは子にあることです。 thread タスク内でシミュレートされた方法でアクティブにスローされる null ポインター例外、および null ポインターによって引き起こされる get メソッドによってスローされる別の ExecutionException。
5. トランザクションのロールバック
上で見たように、
スレッド クラスを通じて Callable インターフェイスを実装しました。 . スレッドの戻り値を取得したり、例外をスローしたりする目的は達成されます。 - Submit はスレッドタスクをスレッドプールに投入し、サブスレッドの実行結果の戻り値 Future を取得できます。
- Future の get() メソッドは、スローされた例外を含む子スレッドの実行情報を取得できます。
-
メイン スレッドのサブスレッドの例外情報を感知またはキャッチできるようになったので、次のステップでメイン スレッドのトランザクションをロールバックするのは簡単すぎるでしょうか?
- jdbc は
conn.rollback()
だけでトランザクションのロールバックを実現します
- Spring 環境では
@Transactional
アノテーションを使用するだけです。
推奨学習: 「Java ビデオ チュートリアル 」
以上がJava の例の詳細な説明: サブスレッドのタスク例外、メインスレッドのトランザクションのロールバックの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。