Java 并发编程学习笔记(13) ----关于ThreadPoolExecutor 线程池构造方法中的各个参数

本文详细解析了ThreadPoolExecutor线程池构造方法中各参数的意义,包括核心线程数、最大线程数、空闲线程存活时间、任务队列类型等,并通过实例展示了不同参数配置下线程池的行为差异。

ThreadPoolExecutor 线程池

1.1 线程池构造方法中各个参数的意义


/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial parameters and default thread factory.
     *
     * @param corePoolSize the number of threads to keep in the pool, even if they are idle,   
     *          unless {@code allowCoreThreadTimeOut} is set
     *      核心线程数,即使空闲也会保存在线程池中,除非设置allowCoreThreadTimeOut
     * @param maximumPoolSize the maximum number of threads to allow in the pool
     *        线程中允许的最大线程数
     * @param keepAliveTime 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.
     *      核心线程之外的空闲线程的回收时间
     * @param unit the time unit for the {@code keepAliveTime} argument
     *      上面时间的单位
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     *      任务队列
     * @param threadFactory the factory to use when the executor creates a new thread
     *      创建线程时使用的工厂,Executors提供了Executors.defaultThreadFactory()
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     *      当处理程序由于已达到线程边界和队列容量而阻塞时,handler被使用
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, handler);
    }

测试类


package com.lhc.concurrent.executor.param;

import java.util.concurrent.*;

public class Constructor {
    public static void main(String[] args) throws InterruptedException{
        Runnable runnable = new Runnable(){
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + " run ! " + System.currentTimeMillis());
                    Thread.sleep(1000);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        };

        ThreadPoolExecutor executor = getPoolBySynchronousQueue();

        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);

        Thread.sleep(300);

        System.out.println("first out core:" + executor.getCorePoolSize());
        System.out.println("first out :" + executor.getPoolSize());
        System.out.println("first out queue:" + executor.getQueue().size());

        Thread.sleep(10000);

        System.out.println("second out core:" + executor.getCorePoolSize());
        System.out.println("second out :" + executor.getPoolSize());
        System.out.println("second out queue:" + executor.getQueue().size());
    }

    /**
     * 如果使用LinkedBlockingDeque来构造,,当线程数量大于corePoolSize时,
     * 其余的任务直接放入队列中,maximumPoolSize参数的作用忽略
     * keepAliveTime参数的作用忽略
     * @return
     */
    public static ThreadPoolExecutor getPoolByLinkedBlockingDeque(){
        return new ThreadPoolExecutor(7, 8, 5,
                TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
    }

    /**
     * 如果使用SynchronousQueue来构造,maximumPoolSize参数的作用生效
     * keepAliveTime参数的作用生效
     * 当启动线程大于maximumPoolSize参数时,不会放入队列,会因为无法处理的任务直接抛出异常
     * @return
     */
    public static ThreadPoolExecutor getPoolBySynchronousQueue(){
        return new ThreadPoolExecutor(7, 8, 5,
                TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
    }
}

1.2 关于 corePoolSize + LinkedBlockingDeque.size


/**
 * 启动线程数大于 corePoolSize + LinkedBlockingDeque.size 时,
 * 会启动非核心线程, 当启动数大于 maxSize + + LinkedBlockingDeque.size 时,
 * 多出来的任务不处理,抛出异常
 */
package com.lhc.concurrent.executor.queue;

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

public class MyLinked {
    public static void main(String[] args){
        Runnable runnable = new Runnable(){
            @Override
            public void run() {
                try{
                    System.out.println("begin " + System.currentTimeMillis());
                    Thread.sleep(1000);
                    System.out.println("end " + System.currentTimeMillis());
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        };

        LinkedBlockingDeque<Runnable> deque = new LinkedBlockingDeque<>(2);
        System.out.println("deque "+ deque.size());
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 5,
                TimeUnit.SECONDS, deque);
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
        executor.execute(runnable);
        System.out.println("deque " + deque.size());
        System.out.println("poolSize " + executor.getPoolSize());
    }
}

Java中,合理配置线程池对于提高并发执行效率至关重要。根据你的需求,推荐深入学习《JAVA并发编程实践-线程池-学习笔记》。这份资料详细介绍了如何配置和调整线程池的高级选项,帮助你理解任务执行框架中需要注意的潜在危险。为了回答你的问题,首先需要理解线程池的基本工作原理。在Java中,线程池利用了Java虚拟机的线程复用机制,通过内部维护的运行队列和线程池,实现了任务的高效分配和执行。 参考资源链接:[JAVA并发编程实践-线程池-学习笔记](https://wenku.youkuaiyun.com/doc/4wwpr5ua9f?spm=1055.2569.3001.10343) 线程池的核心配置参数包括核心线程数、最大线程数、存活时间、工作队列等。核心线程数是线程池中始终维护的线程数,即使它们是空闲的,也会一直存活直到线程池被关闭。最大线程数是线程池能创建的最大线程数量。存活时间是指线程空闲后多少时间会被销毁。工作队列则是用来存放待执行的任务。 通常情况下,你需要根据应用的业务特点和资源限制来配置这些参数。例如,如果你的应用任务大多数是CPU密集型,那么核心线程数和最大线程数不宜设置过大,以避免上下文切换的开销;如果是IO密集型任务,可以适当增加核心线程数以提高并发数。合理的工作队列选择也对性能有重要影响。无界队列可能导致内存溢出,有界队列则可以帮助控制内存使用,但可能会导致任务提交时的阻塞。 在实践中,可以使用ThreadPoolExecutor类来创建线程池,并根据实际情况调整其构造函数中的参数。例如: ```java ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, // 核心线程数 maximumPoolSize, // 最大线程数 keepAliveTime, // 存活时间 TimeUnit.SECONDS, // 存活时间的单位 new LinkedBlockingQueue<Runnable>(), // 工作队列 new ThreadFactory(), // 线程工厂 new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 ); ``` 在配置了线程池之后,还可以通过调整参数来动态应对不同的运行时负载情况,例如使用setCorePoolSize和setMaximumPoolSize等方法动态调整线程池大小。综合这些信息,你可以根据应用的具体需求来合理配置和调整线程池参数,以达到提高并发执行效率的目的。 在深入理解了线程池的工作原理和配置方法后,建议继续参考《JAVA并发编程实践-线程池-学习笔记》中更高级的内容,如线程池的监控、调优和故障排查等,以获得更全面的知识体系。 参考资源链接:[JAVA并发编程实践-线程池-学习笔记](https://wenku.youkuaiyun.com/doc/4wwpr5ua9f?spm=1055.2569.3001.10343)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值