ThreadPoolExecutor参数解析

一、参数

构造函数

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

参数

参数名说明
corePoolSize核心线程数量(常驻)

maximumPoolSize

最大线程数量

keepAliveTime

临时线程存活时间

unit

存活时间单位

workQueue

队列

threadFactory

线程池创建线程对应的工厂

二、源码示例

定义一个线程池包装类(方便使用,也可以使用时候直接创建)

package com.hz.threadpool;

import java.io.Closeable;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description:
 * @author: pp_lan
 * @date: 2022/3/15
 */
public class CustomThreadPool implements Closeable {

    private ThreadPoolExecutor pool;

    private AtomicInteger count = new AtomicInteger();

    private CustomThreadPool(int core, int max, int queueSize, String threadName) {
        this.pool = new ThreadPoolExecutor(core, max, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(queueSize),
                r -> new Thread(r, threadName + count.getAndIncrement()));
    }

    public ThreadPoolExecutor getPool() {
        return pool;
    }

    /**
     * 获取对象
     * @param core
     * @param max
     * @param queueSize
     * @param threadName
     * @return
     */
    public static CustomThreadPool initPool(int core, int max, int queueSize, String threadName) {
        return new CustomThreadPool(core, max, queueSize, threadName);
    }

    /**
     * callable批量任务
     * @param tasks
     * @param <T>
     * @return
     */
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
        try {
            List<Future<T>> futures = this.pool.invokeAll(tasks);
            return futures;
        } catch (InterruptedException e) {
            throw new RuntimeException("线程被中断", e);
        }
    }

    /**
     * callable单个任务
     * @param task
     * @param <T>
     * @return
     */
    public <T> Future<T> submit(Callable<T> task) {
        return this.pool.submit(task);
    }

    /**
     * runnable任务
     * @param runnable
     */
    public void execute(Runnable runnable) {
        this.pool.execute(runnable);
    }

    /**
     * runnable任务
     * @param runnable
     */
    public Future<?> submit(Runnable runnable) {
        return this.pool.submit(runnable);
    }

    /**
     * 线程池关闭,建议使用try-resource进行自动关闭,不要手动执行
     */
    public void shutdown() {
        this.pool.shutdown();
        try {
            if (!this.pool.awaitTermination(1, TimeUnit.MINUTES)) {
                this.pool.shutdownNow();
                if (!this.pool.awaitTermination(1, TimeUnit.MINUTES)) {
                    throw new RuntimeException("线程池关闭失败");
                }
            }
        } catch (InterruptedException e) {
            throw new RuntimeException("线程池关闭失败", e);
        }
    }

    @Override
    public void close() {
        this.shutdown();
    }
}

三、测试

依赖

package com.hz.task;

import java.util.concurrent.TimeUnit;

/**
 * 任务
 *
 * @author pp_lan
 */
public class Task implements Runnable {

    private int index;

    public Task(int index) {
        this.index = index;
    }

    @Override
    public void run() {
        System.out.println("-------------执行任务" + index);
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

参数调试

taskSize <= coreSize + queueSize

package com.hz.task;

import com.hz.threadpool.CustomThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

/**
 * 线程池调参
 *
 * @author pp_lan
 */
public class ThreadPoolParamFixedDemo {

    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolParamFixedDemo.class);

    public static void main(String[] args) {
        Queue<Runnable> queue = new LinkedBlockingDeque<>();
        try (CustomThreadPool pool = CustomThreadPool.initPool(2, 20, 5, "线程池")) {
            for (int i = 0; i < 7; i++) {
                queue.add(new Task(i));
            }

            new Thread(() -> {
                while (true) {
                    Runnable task = queue.poll();
                    if (task != null) {
                        pool.execute(task);
                    } else {
                        try {
                            TimeUnit.SECONDS.sleep(2);
                        } catch (InterruptedException e) {
                            LOGGER.error("休眠被中断", e);
                        }
                    }
                }
            }).start();

            int activeCount = 1;
            while (activeCount > 0) {
                try {
                    System.out.println("wait...");
                    TimeUnit.SECONDS.sleep(1);
                    activeCount = pool.getPool().getActiveCount();
                } catch (InterruptedException e) {
                    LOGGER.error("中断异常", e);
                }
            }
        }
    }

}

运行结果:

wait...
-------------执行任务0
-------------执行任务1
wait...
-------------执行任务2
-------------执行任务3
wait...
-------------执行任务4
-------------执行任务5
wait...
-------------执行任务6
wait...
wait...

此时,从运行结果可见:线程数量=coreSize。

coreSize + queueSize < taskSzie <= maxSize + queueSize

创建新的线程

public static void main(String[] args) {

        ...

        for (int i = 0; i < 25; i++) {
            queue.add(new Task(i));
        }

        ...

    }

运行结果:

wait...
-------------执行任务0
-------------执行任务1
-------------执行任务7
-------------执行任务8
-------------执行任务9
-------------执行任务10
-------------执行任务11
-------------执行任务12
-------------执行任务13
-------------执行任务14
-------------执行任务15
-------------执行任务16
-------------执行任务17
-------------执行任务19
-------------执行任务20
-------------执行任务21
-------------执行任务22
-------------执行任务18
-------------执行任务23
-------------执行任务24
wait...
-------------执行任务2
-------------执行任务3
-------------执行任务4
-------------执行任务5
-------------执行任务6
wait...
wait...
wait...
Disconnected from the target VM, address: '127.0.0.1:35445', transport: 'socket'

Process finished with exit code 130 (interrupted by signal 2: SIGINT)

此时,运行结果可见:coreSize <= 线程数量<=maxSize。

taskSzie > maxSize + queueSize

public static void main(String[] args) {

        ...

        for (int i = 0; i < 26; i++) {
            queue.add(new Task(i));
        }

        ...

    }

运行结果:

-------------执行任务21
-------------执行任务22
-------------执行任务24
-------------执行任务23
Exception in thread "Thread-0" java.util.concurrent.RejectedExecutionException: Task com.hz.task.Task@73c8c9df rejected from java.util.concurrent.ThreadPoolExecutor@625fdb98[Running, pool size = 20, active threads = 20, queued tasks = 5, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
	at com.hz.threadpool.CustomThreadPool.execute(CustomThreadPool.java:72)
	at com.hz.task.TaskQueue.lambda$main$0(TaskQueue.java:33)
	at java.lang.Thread.run(Thread.java:748)
wait...

任务满了,多余任务添加入线程池则执行拒绝策略

四、总结

以demo中的数据为例,coreSize(2), queueSize(5), maxSize(20),实时任务和线程数量对应关系如下所示:

实时任务数量线程数量
[0, 7]2
(7, 25](2, 20]
(25, +\infty)(2, 20], 且多余任务执行拒绝策略,例如报错

注意:

因为只有当taskSize > coreSize + queueSize才会创建新线程,所以创建线程池时候队列需要指定队列长度(反例: new LinkedBlockingDeque()),否则会导致线程数一直为核心线程,即使任务阻塞甚至被拒绝也无法扩展到最大核心数对应的线程数量

LinkedBlockingDeque对应构造函数如下:

public LinkedBlockingDeque() {
    this(Integer.MAX_VALUE);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值