hsingh
hsingh

Reputation: 681

Is java ExecutorService newSingleThreadExecutor performs all the tasks using only one Thread?

I know that a java thread cannot be restarted. So when I submit more than one tasks to newSingleThreadExecutor, then how does it perform all tasks using single thread?

My understanding is that newSingleThreadExecutor will use maximum one thread at a time to process any submitted tasks. I guess same for newFixedThreadPool. If a Thread cannot be restarted then for performing n tasks, n threads should be spawned. I think newSingleThreadExecutor, newFixedThreadPool will make sure that not many threads should be spawned at a same time, like we do without using ExecutorService (where we attach each task with a thread and start separately)

Here is code example

class Task implements Runnable {
    public void run() {
        System.out.println("ThreadID-" + Thread.currentThread().getId());
        try {
            Thread.sleep(100);
        }
        catch (InterruptedException e) {
        }
    }
}

public class SingleThreadExecutorTest {
    public static void main(String[] args) {
        System.out.println("ThreadID-" + Thread.currentThread().getId());
        ExecutorService ex = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            ex.execute(new Task());
        }
    }
}

The above code always prints the same ThreadID.

If I replace below line

Executors.newSingleThreadExecutor();

with

ExecutorService ex = Executors.newFixedThreadPool(2);

Then again it is able to perform all tasks using 2 Threads.

Only when I use

Executors.newCachedThreadPool();

I see different Thread IDs.

How does ExecutorService reuse a Thread? Does it not let it reach to Dead State?

Upvotes: 0

Views: 2487

Answers (1)

xingbin
xingbin

Reputation: 28279

The ThreadPoolExecutor maintains some Worker threads, which work like this:

public class Demo {

    public class Worker implements Runnable {
        @Override
        public void run() {
            Runnable task = getTaskFromQueue();
            while (task != null) {
                task.run();
                task = getTaskFromQueue();  // This might get blocked if the queue is empty, so the worker thread will not terminate
            }
        }
    }

    public static void main(String[] args) {
        Worker worker = new Worker();
        Thread thread = new Thread(worker);
        thread.start();
    }

}

When you submit a task to ThreadPoolExecutor which has a single Worker thread, the calling threads will put the task into a BlockingQueue on below condition:

  • the single Worker is busy
  • the BlockingQueue is not full

And when the Worker is free, it will retrieve new task from this BlockingQueue.

Upvotes: 4

Related Questions