初识java线程池

本文介绍了Java线程池,阐述了使用线程池相较于直接创建线程的好处,如减少系统资源开销、提高响应性等。还介绍了通过Executors创建线程池的几种方式,详细解析了ThreadPoolExecutor的5个参数,并分析了固定、单线程和缓存三种线程池的特点,强调按需创建线程池。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

初识java线程池

为什么使用线程池

在开发中,我们经常会用到线程,通过new Thread()我们可以很快的创建一个线程,执行我们的任务。使用线程池相对于直接new Thread()有以下几个好处:

  1. 减少系统资源开销。线程是稀缺资源,频繁的创建会消耗系统资源,而使用线程池会将线程缓存起来,减少创建线程的开销,线程可以别重复利用
  2. 提高了响应性。当请求到达时,工作线程通常已经存在,因此不会由于等待创建线程而延迟任务的执行
  3. 可以根据系统的承受能力,调整线程中工作线程的数目,防止因为消耗过多的内存,而把服务器搞垮(每个线程需要大约1MB内存,线程创建越多,消耗内存越大)

初识线程池

  1. 创建线程池。在java的juc包中,Executors提供了几种简单的方法,创建线程池

         Executors.newFixedThreadPool(int nThreads); // 创建固定线程池
    
         Executors.newSingleThreadExecutor(); // 创建一个单线程的线程池
    
         Executors.newCachedThreadPool(); // 创建一个缓存线程池
    
  2. 上面列出了比较常用的3种线程池,通过这三种创建线程池的方式,我们可以了解一下线程池的参数的意义。

    // 固定线程池
     public static ExecutorService newFixedThreadPool(int nThreads) {
       return new ThreadPoolExecutor(nThreads, nThreads,
         0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable());
    }
    
    // 单线程的线程池
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
         (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
             new LinkedBlockingQueue<Runnable>()));
    
    // 创建一个缓存线程池
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
         60L, TimeUnit.SECONDS,  new SynchronousQueue<Runnable>());     
    

    可以看到,这三种线程池都是通过ThreadPoolExecutor创建的, ThreadPoolExecutor有5个参数

    1. corePoolSize 保持在线程池中的线程数,当线程数小于corePoolSize时,即使线程时空闲状态,也不回收
    2. maximumPoolSize 允许在线程中的最大线程数,这个和corePoolSize不同之处在于,当线程池中的线程数大于corePoolSize,小于maximumPoolSize时,大于corePoolSize的这部分线程会在空闲的时候被回收
    3. keepAliveTime 线程池中线程数大于corePoolSize时,多出来的线程最多空闲多久被回收
    4. unit keepAliveTime 的时间单位
    5. workQueue 任务队列,在任务被提交后,如果没有空闲线程,任务会被保存在任务队列中
  3. 根据Executors提供的三种线程池使用的参数,我们可以更好的理解上面的5个参数

    1. 固定线程池。可以看到固定线程池的corePoolSize等于maxinumPoolSize,这意味着线程池中的线程的个数会从0开始增长,当增长到corePoolSize时,个数会一直保持不变,不会被回收。由于线程不会被回收,keepAliveTime 和unit 其实没有什么作用。workQueue 是LinkedBlockingQueue<Runnable()),是一个无限大的队列,那么当任务过多时,就会一直积压在任务队列中,有OOM的风险
    2. 单线程线程池。可以看到corePoolSize和maxinumPoolSize都为1,这意味着线程池中的线程个数之只能为1,也就是单线程。和固定线程池一样,keepAliveTime 和unit 没有什么作用。workQuene是一个无限队列
    3. 缓存线程池。corePoolSize为0,maxinumPoolSize为Integer.MAX_VALUE,这意味这线程池中的线程从0开始增长,最大能增长到Integer.MAX_VALUE,当线程空闲的时候会被回收,最后线程完全空闲的时候线程个数会变为0。keepAliveTime 为60,unit 为TimeUnit.SECONDS,这意味这当线程空闲60秒后,就会被回收,workQueue为SynchronousQueue()),这是一个容量为1的队列,只能存放一个任务,所有当任务过多时,线程池会为每一个任务创建一个线程,有OOM的风险。
  4. 通过了解ThreadPoolExecutor的5个构造参数,我们可以根据我们的需要创建线程池,在阿里巴巴开发手册中也强制要求我们自己使用ThreadPoolExecutor去创建
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值