when does executor really create new thread

user7328234 :

I'm confused about when new threads are created as for executor. My understanding is: as for cachedthreadpool, new threads are created according to the submission of tasks. As for fixedthreadpool and singlethread, thread is created in advance regardless of the submission of tasks. Is my understanding wrong?

ExecutorService exec = Executors.newCachedThreadPool(); 
exec.execute(new LiftOff());

ExecutorService exec = Executors.newFixedThreadPool(3); // Are the three threads created 
                                                        // after this line executes?
exec.execute(new LiftOff());

ExecutorService exec = Executors.newSingleThreadExecutor(); // Is the single thread created 
                                                            // after this line executes?
exec.execute(new LiftOff());
hagrawal :

Short answer is that in all cases you mentioned, threads are created only when you start executing the tasks, i.e. no threads will be created after this ExecutorService exec = Executors.newFixedThreadPool(3); line is executed, and first thread will be created only after this exec.execute(new LiftOff()); line is executed.


To better and fully understand this, as @Oliver has advised you need to walk through Java source code and also read about ThreadPoolExecutor, especially what is core pool size, max pool size etc. If you want to quickly understand this in layman's word then read this good answer.

Now, below are few good points to understand before I take you to some sample code:

  • Java's utility class Executors will create and return objects of ExecutorService (please note that ExecutorService is an interface).
  • Now in case of newCachedThreadPool(), newFixedThreadPool(int nThreads) you will get an object of ThreadPoolExecutor (please note that ThreadPoolExecutor implements ExecutorService interface).
  • As you can see in the source code, when you do Executors.newFixedThreadPool(3);, you only get an object of ThreadPoolExecutor with all instance variables like core pool size, max pool size etc. set, and in your case it will be set to 3.
  • At this point no threads are created, and actual thread creation only happens when you start executing tasks using execute, submit or invokeAll.
  • As you can see in source code, when you do first execute it will create only 1 new thread if current pool size is less than core pool size, so this is where your thread start getting created.

Please see below sample code which will help you understand and prove that threads are created only when you start executing the tasks. To explain you, main trick I did is I used the object reference variable of ThreadPoolExecutor so that I can call method like getPoolSize() (please note that getPoolSize() tells about how many threads are currently present in the pool), because when you use object reference variable of ExecutorService then you cannot call these methods (I am sure I need not to tell "why").

When you will run this example you will note that:

  • There were no threads created after ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
  • After first executeRunnable(poolExecutor); you got one thread in the pool.
  • Since you have used core pool size as 3, so after creating 3 threads no more threads were created. (do read about core, max pool size and "queue" size)

package com.learn.stackoverflow.multithreading;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 
 * @author himanshu.agrawal
 *
 */
public class ExecutorServiceNumberOfThreads {
    public static void main(String[] args) {
        System.out.println("### Testing Executors.newFixedThreadPool()");
        testNewFixedThreadPool();
    }

    private static void testNewFixedThreadPool() {
        ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
        System.out.println("Pool when no execute() : " + poolExecutor.getPoolSize());
        executeRunnable(poolExecutor);
        System.out.println("Pool after 1st execute() : " + poolExecutor.getPoolSize());
        executeRunnable(poolExecutor);
        System.out.println("Pool after 2nd execute() : " + poolExecutor.getPoolSize());
        executeRunnable(poolExecutor);
        System.out.println("Pool after 3rd execute() : " + poolExecutor.getPoolSize());
        executeRunnable(poolExecutor);
        System.out.println("Pool after 4th execute() : " + poolExecutor.getPoolSize());
        executeRunnable(poolExecutor);
        System.out.println("Pool after 5th execute() : " + poolExecutor.getPoolSize());
    }

    private static void executeRunnable(ThreadPoolExecutor poolExecutor) {
        poolExecutor.execute(new Runnable() {

            @Override
            public void run() {
                System.out.println("Running: " + Thread.currentThread().getId() + " | " + new Date());
            }
        });
    }

}

Output:

### Testing Executors.newFixedThreadPool()
Pool when no execute() : 0
Pool after 1st execute() : 1
Pool after 2nd execute() : 2
Pool after 3rd execute() : 3
Pool after 4th execute() : 3
Pool after 5th execute() : 3
Running: 10 | Sun Apr 23 19:50:32 IST 2017
Running: 8 | Sun Apr 23 19:50:32 IST 2017
Running: 10 | Sun Apr 23 19:50:32 IST 2017
Running: 9 | Sun Apr 23 19:50:32 IST 2017
Running: 8 | Sun Apr 23 19:50:32 IST 2017

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=457737&siteId=1