Awaitility, Java

Fixed repetition in thread

What to do when you have to run some thread and make it do the same things for X times? We can do it in several ways, but today I am going to show you achieve it using ExecutorService implementations:

  • scheduled thread executor
  • single thread executor

To show you how do they work, I will write two tests, one per each executor thread, but first of all we need to add one dependency to our TDD project:

<dependency>
    <groupId>com.jayway.awaitility</groupId>
    <artifactId>awaitility</artifactId>
    <version>1.7.0</version>
</dependency>

Awaitility, which we have added above, is library used for testing asynchronous code. The main trick is done by waiting until some events occur within some specific time. We can also specify poll interval of condition checking.

Let’s move on to the topic and write tests:

@Test
public void testScheduledExecutorService() throws InterruptedException {
    AtomicInteger i = new AtomicInteger(0);
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.scheduleAtFixedRate(() -> {
        i.incrementAndGet();
        if (i.get() == 10) {
            executorService.shutdown();
        }
    }, 0, 1, TimeUnit.SECONDS);

    await().atMost(10, TimeUnit.SECONDS).until(() -> i.get() == 10);
    assertTrue(executorService.isShutdown());
}

When we want to run scheduled thread for several times it is good idea to use AtomicInteger, which is thread safe. In this test, we run thread  without initial delay. New thread will be executed after exactly 1 second after the last one. When counter i reaches 10, current thread shutdowns executor service, which will no longer call another threads. In the last but one line, awaitility blocks test until within 10 seconds counter reaches 10. At the very end, we check if executor service was shut down properly.

Second test is quite shorter, but does similar things:

@Test
public void testSingleThreadExecutor() throws InterruptedException {
    AtomicInteger i = new AtomicInteger(0);
    Future future = Executors.newSingleThreadExecutor().submit(() -> {
        while (i.incrementAndGet() < 10) ;
    });

    await().atMost(1, TimeUnit.SECONDS).until(() -> i.get() == 10);
    assertTrue(future.isDone());
}

This time the approach is nearly the same, but there is only one thread which has ‘while’ loop. Within this loop we can wait for 1 second each time, but this is not necessary in this case. When we submit() Runnable, we receive Future instance. This object lets us tracking job/thread state. If we don’t want to do that, we can always execute() thread and let it live aside without our care.

ggg

After all we can run both tests. They should pass within less than 10 seconds

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s