assylias
assylias

Reputation: 328608

JUnit and concurrency: inexplicable error

I read in a few posts that using JUnit to test concurrency is not ideal but I have no choice for now. I have just encountered an exception that I can't explain.

I run a test where, in summary:

What could cause that behavior?

Note: I only get the exception from time to time. The code has some non related stuff but I left it there in case I missed something. XXXQuery is an enum.

public void testConcurrent() throws InterruptedException {
    final int N_THREADS = 1000;
    final XXXData xxxData = new AbstractXXXDataImpl();
    final List<QueryResult> results = new ArrayList<>();
    ExecutorService executor = Executors.newFixedThreadPool(N_THREADS);
    for (int i = 0; i < N_THREADS; i++) {
        final int j = i;
        executor.submit(new Runnable() {

            @Override
            public void run() {
                try {
                    results.add(xxxData.get(XXXQuery.values()[j % XXXQuery.values().length]));
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        });
    }
    executor.shutdown();
    executor.awaitTermination(10, TimeUnit.SECONDS);
    assertEquals(N_THREADS, results.size());
}

Upvotes: 0

Views: 171

Answers (1)

Gray
Gray

Reputation: 116878

You cannot add to the results ArrayList in your Runnable.run() method in multiple threads without synchronizing around it.

The assertion failed message is showing that although N_THREADS calls to add() were made, the ArrayList got fewer entries because of concurrency race conditions.

I would use a final array instead of a list. Something like:

final QueryResult[] results = new QueryResult[N_THREADS];
for (int i = 0; i < N_THREADS; i++) {
    ...
        public void run() {
            results[j] = data.get(Query.values()[j % Query.values().length]);
        }

Also, I don't quite get the XXXQuery.values() but I'd pull that into a variable above the loop unless it is changing.

Upvotes: 2

Related Questions