技術共有

メインスレッドが終了し、子スレッドが実行されなくなる

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

問題の背景:

理由は、分散ロックを行う際に単体テストでスレッドを10個作成して起動したためです。各スレッドは run メソッドの内容を出力しますが、テスト結果は実際には何も出力しません。私は非常に困惑しましたが、メインスレッドがサブスレッドの実行を終了して直接終了したのではないかと推測しました。確かに、thread.join() を追加すると期待どおりの結果が得られました。

問題の結論:

main メソッド内に記述されている場合にはこの問題は発生しませんが、単一のテストではこの問題が発生します。

問題のプロセス:

元のコード:

  1. @Test
  2. public void multipleThreadTest(){
  3. System.out.println(Thread.currentThread().getName());
  4. LockThread[] lockThreads = new LockThread[10];
  5. for (int i=0;i< lockThreads.length;i++){
  6. lockThreads[i] = new LockThread(new ZkNodeNoneBlockingLock("app"));
  7. }
  8. for (LockThread lockThread : lockThreads) {
  9. lockThread.start();
  10. }
  11. }
  12. private static class LockThread extends Thread{
  13. ZkNodeNoneBlockingLock locker;
  14. public LockThread(ZkNodeNoneBlockingLock locker){
  15. this.locker = locker;
  16. }
  17. @Override
  18. public void run() {
  19. boolean lock = locker.lock();
  20. System.out.println(this.getName() + (lock ? "上锁成功" : "上锁失败"));
  21. }
  22. }

変更されたコード:

  1. @Test
  2. public void multipleThreadTest(){
  3. System.out.println(Thread.currentThread().getName());
  4. LockThread[] lockThreads = new LockThread[10];
  5. for (int i=0;i< lockThreads.length;i++){
  6. lockThreads[i] = new LockThread(new ZkNodeNoneBlockingLock("app"));
  7. }
  8. for (LockThread lockThread : lockThreads) {
  9. lockThread.start();
  10. }
  11. for (LockThread lockThread : lockThreads){
  12. try {
  13. lockThread.join();
  14. } catch (InterruptedException e) {
  15. throw new RuntimeException(e);
  16. }
  17. }
  18. }
  19. private static class LockThread extends Thread{
  20. ZkNodeNoneBlockingLock locker;
  21. public LockThread(ZkNodeNoneBlockingLock locker){
  22. this.locker = locker;
  23. }
  24. @Override
  25. public void run() {
  26. boolean lock = locker.lock();
  27. System.out.println(this.getName() + (lock ? "上锁成功" : "上锁失败"));
  28. }
  29. }

注記:

Thread.join() は現在のスレッドです。つまり、メインスレッドはスレッド thread の実行が完了するまで実行を続けることができません。