使用多个并发线程执行一组测试方法

时间:2016-08-09 17:39:15

标签: java multithreading junit concurrency

基于JUnit的代码将每个运行这3个方法作为10个并发线程。

@RunWith(SpringJUnit4ClassRunner.class
@SpringBootTest
public class TestClass {


    @Test
    public void readFromDBOneRecord(){
       try {
         dbService.findOneByID("1");
       } catch (Exception error) {
             Assert.fail("Unexpected error occured .");
       }
    }

    @Test
    public void writeToDBOneRecord(){
       try {
             dbService.save(entity.builder()
                            .setID("1").setName("John").build())
       } catch (Exception error) {
             Assert.fail("Unexpected error occured .");
       }
    }

    @Test
    public void deleteDbRecord(){
       try {
          dbService.delete("1");
       } catch (Exception error) {
             Assert.fail("Unexpected error occured .");
       }
    }
}

在某些情况下,某些方法会抛出异常。就像在delete之前执行writeToDBOneRecord一样。 因此,每个方法只能说3个线程,例如:

OperationNr|| OperationName || [ThreadNr/total threads per method]OperationType

     1.        write        [2/3]w
     2.        read         [1/3]r
     3.        read         [3/3]r
     4.        delete       [2/3]d
     5.        read         [2/3]r
     6.        delete       [3/3]d ->exception no record
     7.        write        [1/3]w
     8.        write        [3/3]w ->exception record already present
     9.        delete       [1/3]d

在10个并发线程中共执行这3个测试方法的代码是什么(总共30个)?

1 个答案:

答案 0 :(得分:2)

由于你想并行完成所有事情,我会混合所有内容并依赖CountDownLatch个实例来同步下一个线程:

@Test
public void testMultiThreading() throws Exception {
    // Total of reader threads
    int reader = 5;
    // Total of writer threads
    int writer = 3;
    // Total of remover threads
    int remover = 1;
    // CountDownLatch used to release all the threads at the same time
    final CountDownLatch startSignal = new CountDownLatch(1);
    // CountDownLatch used to be notified when all threads did their task
    final CountDownLatch doneSignal = new CountDownLatch(reader + writer + remover);
    // List in which we collect all the errors
    final List<Exception> errors = Collections.synchronizedList(new ArrayList<>());
    // Create all the reader threads and start them
    for (int i = 0; i < reader; i++) {
        Thread thread = new Thread() {
            public void run() {
                try {
                    startSignal.await();
                    dbService.findOneByID("1");
                } catch (Exception e) {
                    errors.add(e);
                } finally {
                    doneSignal.countDown();
                }
            }
        };
        thread.start();
    }
    // Create all the writer threads and start them
    for (int i = 0; i < writer; i++) {
        Thread thread = new Thread() {
            public void run() {
                try {
                    startSignal.await();
                    dbService.save(entity.builder()
                        .setID("1").setName("John").build());
                } catch (Exception e) {
                    errors.add(e);
                } finally {
                    doneSignal.countDown();
                }
            }
        };
        thread.start();
    }
    // Create all the remover threads and start them
    for (int i = 0; i < remover; i++) {
        Thread thread = new Thread() {
            public void run() {
                try {
                    startSignal.await();
                    dbService.delete("1");
                } catch (Exception e) {
                    errors.add(e);
                } finally {
                    doneSignal.countDown();
                }
            }
        };
        thread.start();
    }
    // Release the threads
    startSignal.countDown();
    // Wait until all threads did their task
    doneSignal.await();
    // If an error has been collected, print the stack trace and throws the
    // first error to make the test fail
    if (!errors.isEmpty()) {
        for (Exception e : errors) {
            e.printStackTrace();
        }
        throw errors.get(0);
    }
}

NB:如果您希望由多个并发线程执行给定的单元测试,请查看contiperf,但它不允许您根据需要混合它们实现