1

Since the service is single threaded, the monkey1 loop series will always get executed before monkey2, so we can expect monkey1 will always be greater than monkey2, can't we?

import java.util.concurrent.*;

public class MonkeyCounter {
    private static AtomicInteger monkey1 = new AtomicInteger(0); 
    private static AtomicLong monkey2 = new AtomicLong(0);

    public static void main(String[] args) {
      ExecutorService service = null;
      try {
        service = Executors.newSingleThreadExecutor(); 

        for(int i=0; i<100; i++)
        service.submit(() -> monkey1.getAndIncrement()); 
        for(int i=0; i<100; i++)
        service.submit(() -> monkey2.incrementAndGet());
        System.out.println(monkey1+" "+monkey2); 
      } finally {
       if(service != null) service.shutdown();
      }
    }
}
Butiri Dan
  • 1,759
  • 5
  • 12
  • 18
Treefish Zhang
  • 1,131
  • 1
  • 15
  • 27
  • 1
    The way code is written monkey1 will be greater than monkey2, but it is not the correct implementation as the main thread is not waiting for the other thread to finish and notify. – AK DevCraft Sep 11 '19 at 02:52

2 Answers2

3

Javadoc on Executors.newSingleThreadExecutor:

Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.

Tasks are placed in a queue. Queue are FIFO so with single thread, the monkey1 > monkey2 is guaranteed if none of the increment fails.

Bear in mind that value of monkey1 and monkey2 are undetermined because you do not wait for the jobs completion.

Mạnh Quyết Nguyễn
  • 17,677
  • 1
  • 23
  • 51
0

After Holger corrected me, with Executors.newSingleThreadExecutor() tasks are guaranteed to execute sequentially.

In following example even if the first batch of tasks being submitted are blocking for 5 secs, are completed first than the second batch of tasks with no blocking other than println.

example,

import java.util.concurrent.*;

public class ExecutorServiceTests {

    public static void main(String[] args) {
        java.util.concurrent.ExecutorService service = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 5; i++) {
            service.submit(() -> {
                block(5000);
                System.out.println("execution1");
            });
        }

        for (int i = 0; i < 5; i++) {
            service.submit(() -> {
                System.out.println("execution2");
            });
        }

        service.shutdown();
    }

    private static void block(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Output:

execution1
execution1
execution1
execution1
execution1
execution2
execution2
execution2
execution2
execution2
prayagupa
  • 30,204
  • 14
  • 155
  • 192
  • This setup is not similar to OP's setup – Mạnh Quyết Nguyễn Sep 11 '19 at 03:12
  • Your second loop does not submit tasks. It does not prove anything regarding the behavior of the executor. `ExecutorService` is an interface, so you have to refer to an actual implementation when you describe the behavior. In case of `Executors.newSingleThreadExecutor()`, your description is just wrong. – Holger Sep 11 '19 at 07:42