【问题标题】:How does maximumPoolSize of ThreadPoolExecutor works?ThreadPoolExecutor 的 maximumPoolSize 是如何工作的?
【发布时间】:2012-09-02 14:23:22
【问题描述】:

我正在尝试了解 ThreadPoolExecutor 类。我已阅读此 answer 和 Javadoc。但我的实验与描述不符:

我使用工厂初始化线程池以跟踪 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;
    }

}

然后是任务:

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);
        } 

    }

}

并为按钮分配操作:

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

但是我向该按钮发送垃圾邮件,并且从未创建第三个线程,那么 ThreadPoolExecutor 构造函数 (maximumPoolSize=4) 中的第二个参数是什么。 我预计在执行结束 1 分钟后将创建 4 个线程,其中 2 个线程将被杀死

【问题讨论】:

  • 是因为你的线程在休眠吗?也许改变你的 runnable 做一个忙碌的等待会给你你期望的结果

标签: java android multithreading


【解决方案1】:

来自ThreadPoolExecutor 的 API:

如果大于 corePoolSize 但小于 maximumPoolSize 线程运行,只有当队列被创建时才会创建一个新线程 满了。

您的队列永远不会填满,因为它的容量为1000。如果您将容量更改为1,您将看到正在创建Threads。

Executors 类将SynchronousQueue 用于其newCachedThreadPool 方法,因此您可能也需要考虑使用它。

【讨论】:

  • 如果我减少值,我会得到 java.util.concurrent.RejectedExecutionException
  • 一旦您首先减少数量,它就会达到 maxPoolSize 限制,然后它会拒绝任务。因此您可以在此异常之前打印池大小,该大小等于 maxpoolsize。
【解决方案2】:

在 ThreadPoolExecutor 中,maxPoolSize 出现在 corePoolSize no 不足以执行您的任务并且如果所有 no 都被任务占用,那么只会再创建一个线程来执行任务。这个 no 可以增长到 maxPoolSize。

编辑您误解了 maxPoolsize 概念。请参阅下面的链接。

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

【讨论】:

  • 所以当我向按钮发送垃圾邮件时,应该创建额外的 2 个线程直到 maximumPoolSize 对吗?
  • +1 for ,以这个例子为例。起始线程池大小为 1,核心池大小为 5,最大池大小为 10,队列为 100。Sun 的方式:随着请求的进入,线程将创建最多 5 个,然后将任务添加到队列中,直到达到100. 当队列满时,新线程将被创建到 maxPoolSize。一旦所有线程都在使用并且队列已满,任务将被拒绝。随着队列的减少,活动线程的数量也会减少。
【解决方案3】:

要使 ThreadPool 创建新的附加线程(根据 ma​​ximumPoolSize 参数扩展池大小)尝试执行这个简单的示例:

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;
        }

    }
}

您将获得展示 ma​​ximumPoolSizekeepAliveTime 影响的输出:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 2018-03-21
    • 2018-10-04
    • 2021-03-08
    相关资源
    最近更新 更多