简体   繁体   中英

Does ScheduledExecutorService guarantee order when pool size is one?

I have a ScheduledExecutorService that has a pool size of 1 threads.

If I schedule many tasks using that service with the same delay, is the order of scheduling preserved during the execution?

Yes, as long as the scheduler implementation used will follow the interface specification. For example, new ScheduledThreadPoolExecutor(1) will use a DelayedWorkQueue which will preserve the order.

As per javadoc all ScheduledExecutorService implementations should preserve order:

Tasks scheduled for exactly the same execution time are enabled in first-in-first-out (FIFO) order of submission.

One can test the implementation with the example below:

import com.google.code.tempusfugit.concurrency.IntermittentTestRunner;
import com.google.code.tempusfugit.concurrency.annotations.Intermittent;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

import static org.assertj.core.api.Assertions.assertThat;


@RunWith(IntermittentTestRunner.class)
public class ScheduledExecutorServiceTest {
    @Test
    @Intermittent(repetition = 20)
    public void preservesOrderOfTasksScheduledWithSameDelay() throws InterruptedException {
        ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);

        AtomicInteger atomicInteger = new AtomicInteger(0);
        int numTasks = 1_000;
        CountDownLatch countDownLatch = new CountDownLatch(numTasks);
        for (int i = 0; i < numTasks; i++) {
            int finalI = i;
            scheduledExecutorService.schedule(() -> {
                atomicInteger.compareAndSet(finalI, finalI + 1);
                countDownLatch.countDown();
            }, 10, TimeUnit.MILLISECONDS);
        }
        countDownLatch.await();

        assertThat(atomicInteger.get()).isEqualTo(numTasks);
    }
}

Yes, the order is preserved. From the javadocs

Delayed tasks execute no sooner than they are enabled, but without any real-time guarantees about when, after they are enabled, they will commence. Tasks scheduled for exactly the same execution time are enabled in first-in-first-out (FIFO) order of submission.

You can see this in action too

    public static void main(String args[]) {
        ScheduledExecutorService e = Executors.newScheduledThreadPool(1);
        
        e.schedule(delay("delay for 1 second", 10), 1, TimeUnit.SECONDS);
        e.schedule(delay("delay for 5 second", 0), 5, TimeUnit.SECONDS);
        e.schedule(delay("delay for 3 second", 0), 3, TimeUnit.SECONDS);
        e.schedule(delay("delay for 7 second", 0), 7, TimeUnit.SECONDS);
        e.schedule(delay("delay for 2 second", 0), 2, TimeUnit.SECONDS);
    }
    
    private static Runnable delay(String message, int initialDelay) {
        return () -> {
            Thread.sleep(initialDelay);
            System.out.println(message);
        };
    }

prints

delay for 1 second
delay for 2 second
delay for 3 second
delay for 5 second
delay for 7 second

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM