8.线程池

线程池

池化技术

程序的运行,本质:占用系统的资源,优化资源的使用

线程池,连接池,内存池,对象池,常量池

线程池好处:

  1. 降低资源消耗
  2. 提高响应速度
  3. 方便管理

线程复用,可以控制最大并发数,管理线程

线程池:三大方法

在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了资源的开销。而线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式,这一方面是由于jdk中Executor框架虽然提供了如newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool()等创建线程池的方法,但都有其局限性,不够灵活;另外由于前面几种方法内部也是通过ThreadPoolExecutor方式实现,使用ThreadPoolExecutor有助于大家明确线程池的运行规则,创建符合自己的业务场景需要的线程池,避免资源耗尽的风险。

//Executors 工具类 三大方法
public class Demo01 {
    public static void main(String[] args) {
        //ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
        //ExecutorService threadPool =Executors.newFixedThreadPool(3);//固定数量线程池
        ExecutorService threadPool =Executors.newCachedThreadPool();//可伸缩,遇强则强,遇弱则弱
        try {
            for (int i = 1; i <= 10; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            threadPool.shutdown();
        }
    }
}

7大参数

源码分析

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}

//本质:ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,//核心线程池大小
                          int maximumPoolSize,//最大线程池大小
                          long keepAliveTime,//超时了 没人调用就会释放
                          TimeUnit unit,//超时单位
                          BlockingQueue<Runnable> workQueue,//阻塞队列,
当请求的线程数大于 corePoolSize时,线程进入该阻塞队列
                          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.acc = System.getSecurityManager() == null ?
            null :
            AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

自定义线程池

拒绝策略
1.AbortPolicy() 满了,抛出异常
2.CallerRunsPolicy 哪来的那里去
3.DiscardOldestPolicy 满了,尝试和最早的任务竞争,竞争失败也不会抛出异常
4.DiscardPolicy 满了,丢掉任务,不会抛出异常
//自定义线程池
/*
拒绝策略
1.AbortPolicy() 满了,抛出异常
2.CallerRunsPolicy 哪来的那里去
3.DiscardOldestPolicy 满了,尝试和最早的任务竞争,竞争失败也不会抛出异常
4.DiscardPolicy 满了,丢掉任务,不会抛出异常
*
* */
public class Demo02 {
    public static void main(String[] args) {

        /*最大线程数如何定义
        * 1.CPU密集型 几核就是几,可以保持CPU效率最高
        *2.IO 密集型  判断你程序中十分耗IO的线程,最大线程数=IO*2
        * 程序中有15个大型任务,最大线程15*2=30
        * */
        //获取cpu核数
        int cpu = Runtime.getRuntime().availableProcessors();
        System.out.println(cpu);
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2,
                5,
                3, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()//银行满了,还有人进来,不处理这个人的,抛出异常
        );
        try {
            //最大8个=队列+max=3+5
            //超过8,抛出异常RejectedExecutionException,由拒绝策略决定
            for (int i = 1; i <= 9; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + " ok");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }

    }
}

拓展

最大线程数如何定义

  • CPU密集型 几核就是几,可以保持CPU效率最高

  • IO 密集型 判断你程序中十分耗IO的线程,最大线程数=IO*2

    程序中有15个大型任务,最大线程15*2=30

posted @   jpy  阅读(4)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示