10

I'm trying to understand ThreadPoolExecutor class. I have read this answer and the Javadoc. But my experimentation doesn't match with that description:

I initialize the threadpool with an factory for tracking the ids

int tcounter = 0;
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 1, TimeUnit.MINUTES,
        new ArrayBlockingQueue<Runnable>(1000), new ThreadFactory() {

            @Override
            public Thread newThread(Runnable r) {
                return new mThread(tcounter++, r);
            }
        });

public class mThread extends Thread {
    int id;

    private mThread(int id, Runnable run) {
        super(run);
        GLog.e("created thread " + id);
        this.id = id;
    }

}

then the task:

public class mRunanble implements Runnable {
    int value = 0;

    private mRunanble(int value) {
        super();
        this.value = value;
    }

    @Override
    public void run() {
        SystemClock.sleep(3000);
        Thread t = Thread.currentThread();
        if (t instanceof mThread) {

            GLog.e("Say " + (value) + " on thread " + ((mThread) t).id);
        } 

    }

}

and assign a button the action:

executor.execute(new mRunanble(i++));

But I spam that button and the third thread is never created, so what is for the second paramether in the ThreadPoolExecutor constructor (maximumPoolSize=4). I was specting 4 threads to be created and 2 of them to be killed after 1 minute of the end of the execution

Community
  • 1
  • 1
Addev
  • 31,819
  • 51
  • 183
  • 302
  • is it because your threads are sleeping? perhaps changing your runnable to do a busy wait will give you the result you are expecting – happymeal Sep 02 '12 at 14:37

3 Answers3

7

From the API for ThreadPoolExecutor:

If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.

Your queue never fills since it has a capacity of 1000. If you change the capacity to 1, you will see Threads being created.

The Executors class uses a SynchronousQueue for its newCachedThreadPool methods, so you might want to consider using it as well.

Jeffrey
  • 44,417
  • 8
  • 90
  • 141
  • If I reduce the value I get an java.util.concurrent.RejectedExecutionException – Addev Sep 02 '12 at 14:48
  • 1
    as soon you reduce the number first it reaches maxPoolSize limit and then it rejects the tasks.so you can print the pool size just before this exception that would be equal to maxpoolsize. – amicngh Sep 02 '12 at 14:58
  • The ThreadPoolExecutor works in Android the same way, the doc also stats: Else if fewer than maximumPoolSize threads are running, a new thread will be created to handle the request only if the queue is full. – bulletProofCat Aug 15 '23 at 02:40
2

In ThreadPoolExecutor maximumPoolSize comes in picture when corePoolSize no is not sufficient to execute your tasks and if all no are ocupied by tasks then only one more tread is being created to execute task .this no can grow upto maxPoolSize.

Edit you missunderstood the maxPoolsize concept.please refer below link.

http://www.bigsoft.co.uk/blog/index.php/2009/11/27/rules-of-a-threadpoolexecutor-pool-size

amicngh
  • 7,831
  • 3
  • 35
  • 54
  • So when I spam the button the additional 2 threads until maximumPoolSize should be created right? – Addev Sep 02 '12 at 14:36
  • 3
    +1 for , Take this example. Starting thread pool size is 1, core pool size is 5, max pool size is 10 and the queue is 100. Sun’s way: as requests come in threads will be created up to 5, then tasks will be added to the queue until it reaches 100. When the queue is full new threads will be created up to maxPoolSize. Once all the threads are in use and the queue is full tasks will be rejected. As the queue reduces so does the number of active threads. – Tushar Pandey Aug 08 '13 at 07:13
1

To make ThreadPool create new additional thread (to extend pool size according to maximumPoolSize parameter) try to execute this simple example:

public class Main {

    public static void main(String[] args) throws InterruptedException {

        ThreadPoolExecutor tpe = new ThreadPoolExecutor(
                1, 2, 500, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1));
        System.out.println("init pool size= " + tpe.getPoolSize() + ", queue size=" + tpe.getQueue().size());

        tpe.execute(new Task("1st", 10000));
        Thread.sleep(1000);
        print(tpe, "1st");

        tpe.execute(new Task("2nd", 0));
        Thread.sleep(1000);
        print(tpe, "2nd");

        tpe.execute(new Task("3d", 2000));
        Thread.sleep(1000);
        print(tpe, "3d");

        while (tpe.getPoolSize()>1) {           
            Thread.sleep(100);
        }
        System.out.println("pool size= " + tpe.getPoolSize() + ", queue size=" + tpe.getQueue().size());
        tpe.shutdown();
    }

    private static void print(ThreadPoolExecutor tpe, String name) {
        System.out.println("After " + name + " execute -  pool size= " + tpe.getPoolSize() + ", queue=" + tpe.getQueue());
    }

    private static class Task implements Runnable {

        private final String name;
        private final long time;

        Task(String name, long time) {
            this.name = name;
            this.time = time;
        }

        @Override
        public void run() {
            System.out.println("Run " + Thread.currentThread().getName() + "-" + name);
            try {
                Thread.sleep(time);
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
            System.out.println("Finish " + Thread.currentThread().getName() + "-" + name);
        }

        @Override
        public String toString() {
            return name;
        }

    }
}

You'll get the output which demonstrates impact of maximumPoolSize and keepAliveTime:

init pool size= 0, queue size=0
Run pool-1-thread-1-1st
After 1st execute -  pool size= 1, queue=[]
After 2nd execute -  pool size= 1, queue=[2nd]
Run pool-1-thread-2-3d
After 3d execute -  pool size= 2, queue=[2nd]
Finish pool-1-thread-2-3d
Run pool-1-thread-2-2nd
Finish pool-1-thread-2-2nd
pool size= 1, queue size=0
Finish pool-1-thread-1-1st
Dmytro Kryvenko
  • 343
  • 4
  • 16