8

1 から 20 までの数字のテーブルを生成するスレッドの簡単な例を書きました。 main メソッドでテストすると、すべてのスレッドが実行され (すべてのメッセージが出力されます)、すべてのスレッドが実行されていません (すべてのメッセージが実行されていません)。 JUnitテストで同じことを行うと、ほとんどの場合(すべてのスレッドが実行されることもあります)。アウトプットに関しては、差があってはならないと思います。

main メソッドを持つクラスは次のとおりです。

public class Calculator implements Runnable {

    private int number;

    Calculator(final int number){
        this.number = number;
    }

   @Override
   public void run() {
        for(int i = 1; i <= 10; i++){
            System.out.printf("%s : %d * %d =  %d \n", Thread.currentThread().getName(), number, i, number * i);
        }

   }

    public static void main(String[] args){
        Calculator calculator = null;
        Thread thread = null;
        for(int i = 1; i < 21; i ++){
            calculator = new Calculator(i);
            thread = new Thread(calculator);
            System.out.println(thread.getName() + " Created");
            thread.start();
            System.out.println(thread.getName() + " Started");
        }

     }

}

main メソッドを呼び出すと、すべての結果が出力されます。

以下は、main メソッドに相当する JUnit テストのコードです。

public class CalculatorTest {

private Calculator calculator;
private Thread thread;

@Test
public void testCalculator() {
    for(int i = 1; i < 21; i ++){
        calculator = new Calculator(i);
        thread = new Thread(calculator);
        System.out.println(thread.getName() + " Created");
        thread.start();
        System.out.println(thread.getName() + " Started");
     }
 }

}

上記のテスト ケースを実行すると、出力の動作がシーンで一貫しておらず、すべてのメッセージが出力される場合があり、ほとんどの場合、少数しか出力されずに終了します。上記の JUnit テスト ケースの場合にキャプチャされた出力を次に示します。

Thread-0 Created
Thread-0 Started
Thread-1 Created
Thread-1 Started
Thread-2 Created
Thread-2 Started
Thread-3 Created
Thread-3 Started
Thread-4 Created
Thread-4 Started
Thread-5 Created
Thread-5 Started 
Thread-6 Created
Thread-6 Started
Thread-7 Created
Thread-7 Started
Thread-8 Created
Thread-8 Started
Thread-9 Created
Thread-9 Started
Thread-10 Created
Thread-10 Started
Thread-11 Created
Thread-11 Started
Thread-12 Created
Thread-12 Started
Thread-13 Created
Thread-13 Started
Thread-14 Created
Thread-14 Started
Thread-15 Created
Thread-15 Started
Thread-16 Created
Thread-16 Started
Thread-17 Created
Thread-17 Started
Thread-18 Created  
Thread-18 Started
Thread-19 Created 
Thread-19 Started
Thread-0 : 1 * 1 =  1 
Thread-0 : 1 * 2 =  2 
Thread-0 : 1 * 3 =  3 
Thread-0 : 1 * 4 =  4 
Thread-0 : 1 * 5 =  5 
Thread-0 : 1 * 6 =  6 
Thread-0 : 1 * 7 =  7 
Thread-0 : 1 * 8 =  8 
Thread-0 : 1 * 9 =  9 
Thread-0 : 1 * 10 =  10 
Thread-2 : 3 * 1 =  3 
Thread-2 : 3 * 2 =  6 
Thread-2 : 3 * 3 =  9 
Thread-2 : 3 * 4 =  12 
Thread-2 : 3 * 5 =  15 
Thread-2 : 3 * 6 =  18 
Thread-2 : 3 * 7 =  21 

出力は、他のスレッドで残りのメッセージを出力したり、他のスレッドを実行したりせずに、ここで終了します。

誰かがこの背後にある理由を理解するのを手伝ってくれますか? 前もって感謝します。

4

2 に答える 2

5

生成されたすべてのスレッドが終了する前に、テスト メソッドが終了します。JUnit エグゼキュータが終了すると、生成されたすべてのスレッドが強制終了されます。

この種のテストを実行する場合は、作成したスレッドのコレクションと、join()テスト メソッドの最後にそれぞれのスレッドを保持する必要があります。各スレッドへの呼び出しjoin()は、2 番目のループで実行されます (すべてのスレッドを開始するループに続きます)。

このようなもの:

@Test
public void testCalculator() {
    List<Thread> threads = new ArrayList<>();
    for (int i = 1; i < 21; i++) {
        calculator = new Calculator(i);
        thread = new Thread(calculator);
        threads.add(thread);
        System.out.println(thread.getName() + " Created");
        thread.start();
        System.out.println(thread.getName() + " Started");
    }
    for (Thread thread : threads) {
        thread.join();
    }
 }

すべてのスレッドをほぼ同時に開始したい場合 (たとえば、スレッドを作成しているループがループのたびに重要な作業を行う場合):

@Test
public void testCalculator() {
    List<Thread> threads = new ArrayList<>();
    for (int i = 1; i < 21; i++) {
        threads.add(new Thread(new Calculator(i)));
    }
    for (Thread thread : threads) {
        thread.start();
    }
    for (Thread thread : threads) {
        thread.join();
    }
}
于 2013-05-24T16:14:17.827 に答える