JavaSE-线程池(2)- 线程池参数

JavaSE-线程池(2)- 线程池参数

在上篇线程池概念中提到创建线程池可以使用工具类Executors中的静态方法,比如使用 Executors.newFixedThreadPool 方法可以创建一个拥有固定线程数的线城池,这个方法内部实例化了ThreadPoolExecutor,ThreadPoolExecutor 构造方法如下:

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

上述构造方法包含5个参数,其中调用的 this 构造方法如下,新增了 ThreadFactory (创建线程的工厂),RejectedExecutionHandler (任务过多时的拒绝策略)参数:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

corePoolSize (核心线程数):

the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set

线程池中保留的最少线程数量,除非调用 ThreadPoolExecutor 实例方法 allowCoreThreadTimeOut(true),否则即使核心线程空闲也不会被回收

maximumPoolSize (最大线程数):

the maximum number of threads to allow in the pool

线程池中允许的最大线程数

keepAliveTime (空闲线程存活时长,配合TimeUnit unit 使用):

when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.

超过corePoolSize 数量的非核心线程在终止之前等待的最大时长

unit (空闲线程存活时长单位):

the time unit for the keepAliveTime argument

workQueue (任务等待队列):

the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.

当核心线程处于非空闲状态并且有新的任务提交时,线程池会将这些任务放入等待队列中

threadFactory(线程工厂):

the factory to use when the executor creates a new thread

创建线程时使用的工厂,可以自定义线程创建方式,如自定义线程名

handler(拒绝策略):
当线程池等待队列添加任务的数量达到最大限制,并且运行的线程数量达到 maximumPoolSize 时,如果还有新任务被提交,线程池将执行此策略
默认拒绝策略

ThreadPoolExecutor 线程池执行过程

ThreadPoolExecutor根据corePoolSize和maximumPoolSize设置的边界自动调整池的大小,当在方法execute(Runnable)中提交一个新任务时,如果正在运行的线程少于corePoolSize,则创建一个新线程来处理请求,即使其他工作线程处于空闲状态。如果提交任务后 处理任务需要的线程数 > corePoolSize,则此时任务会添加到任务队列(上述代码中 BlockingQueue 参数),当提交的任务较多任务队列填充满时,则新建一个线程来处理新提交的任务(此处假设 maximumPoolSize > corePoolSize),如果运行的线程数达到 maximumPoolSize 时还有新提交的任务,则线程池执行拒绝策略(上述 RejectedExecutionHandler 参数),当线程池处理完任务后,核心线程不会被会回收,但是非核心线程(数量为: maximumPoolSize - corePoolSize )在空闲 keepAliveTime (单位为 入参TimeUnit )时长后被回收

举例说明

在以下例子中,创建了一个 corePoolSize 为2,maximumPoolSize 为4,队列长度为2 的线程池,往该线程池中提交8个任务(每个任务执行时长为2秒),开始时线程池中没有线程,当提交 1,2 任务时创建1,2线程处理这两个任务,当提交3,4任务时,由于1,2线程还在处理1,2任务,所以3,4任务被添加到等待队列中,当提交5,6任务时由于队列满了,所以线程池新建3,4线程来处理,当提交7,8任务时,由于线程数量已经达到maximumPoolSize并且1,2,3,4线程都没有处于空闲状态,线程池只能执行拒绝策略

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolExecutorTest1 {

    static class MyThreadFactory implements ThreadFactory {
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix = "myPool-thread-";

        MyThreadFactory() {
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
            t.setDaemon(false);
            return t;
        }
    }

    static class MyTask implements Runnable {

        private int i;

        public MyTask(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread() + " " + i);
        }
    }

    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 4,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(2),
                new MyThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

        for (int i = 1; i <= 8; i++) {
            try {
                threadPoolExecutor.execute(new MyTask(i));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        threadPoolExecutor.shutdown();
    }
}

执行结果:

java.util.concurrent.RejectedExecutionException: Task com.hs.example.base.multithread.threadpool.ThreadPoolExecutorTest1$MyTask@763d9750 rejected from java.util.concurrent.ThreadPoolExecutor@d70c109[Running, pool size = 4, active threads = 4, queued tasks = 2, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at com.hs.example.base.multithread.threadpool.ThreadPoolExecutorTest1.main(ThreadPoolExecutorTest1.java:50)
java.util.concurrent.RejectedExecutionException: Task com.hs.example.base.multithread.threadpool.ThreadPoolExecutorTest1$MyTask@22a71081 rejected from java.util.concurrent.ThreadPoolExecutor@d70c109[Running, pool size = 4, active threads = 4, queued tasks = 2, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at com.hs.example.base.multithread.threadpool.ThreadPoolExecutorTest1.main(ThreadPoolExecutorTest1.java:50)
Thread[myPool-thread-1,5,main] 1
Thread[myPool-thread-2,5,main] 2
Thread[myPool-thread-4,5,main] 6
Thread[myPool-thread-3,5,main] 5
Thread[myPool-thread-2,5,main] 4
Thread[myPool-thread-1,5,main] 3

线程池执行流程图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值