JUC入门(五)

#新星杯·14天创作挑战营·第11期#

11、线程池(重点)

线程池有三大方法、七大参数、4中拒绝策略

什么是池化技术

简单理解:预先创建,要用就拿

池化”(Pooling)是一种资源管理技术,用于优化资源的使用效率,减少资源创建和销毁的开销。池化技术的核心思想是预先创建并维护一组资源对象(如线程、数据库连接、对象实例等),当需要使用这些资源时,从池中获取一个可用的资源,使用完毕后将其归还到池中,而不是每次都重新创建和销毁资源。

这里讲述池化技术之一>线程池

线程池的好处:

  • 减少线程创建和销毁的开销:线程的创建和销毁是相对耗时的操作,线程池通过复用线程,避免了频繁的线程创建和销毁,从而提高了程序的性能。
  • 提高线程的可管理性:线程池可以对线程进行统一管理,例如限制线程的最大数量、设置线程的优先级等,避免线程过多导致的系统资源耗尽问题。
  • 提高响应速度:当有任务到来时,可以直接从线程池中获取线程执行,而不需要等待线程的创建,从而提高了系统的响应速度。

下面用自定义线程池的代码演示三大方法,七大参数、四大拒绝策略

package com.yw.Threadchi;


import java.util.concurrent.*;

public class Demo1 {
    public static void main(String[] args) {
        //三大线程池操作,不建议,可能会造成资源损耗
//        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();//单个线程
//        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);//创建一个固定大小的线程池
//        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();//可伸缩的线程池,可根据情况调节自身大小


        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());


            try {
                for (int i = 0;i < 9;i++) {
                    threadPoolExecutor.execute(() -> {
                        System.out.println(Thread.currentThread().getName() + "OK~");
                    });
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                threadPoolExecutor.shutdown();
            }
        }
    }

corePoolSize

含义:核心线程数,即线程池中始终保持的线程数量。

作用

  • 当线程池中的线程数量小于 corePoolSize 时,即使有线程空闲,线程池也会优先创建新的线程来处理任务。
  • 这些核心线程默认会一直存活,即使它们处于空闲状态,也不会被销毁(除非设置了 allowCoreThreadTimeOuttrue)。
maximumPoolSize

含义:最大线程数,即线程池中允许的最大线程数量。

作用

  • 当线程池中的线程数量达到 corePoolSize 且任务队列已满时,线程池会尝试创建新的线程来处理任务,但线程数量不会超过 maximumPoolSize
  • 如果线程池中的线程数量已经达到 maximumPoolSize,且任务队列已满,此时再有新任务提交,线程池会拒绝执行任务,并抛出 RejectedExecutionException 异常(除非设置了拒绝策略)。
keepAliveTime

含义:非核心线程的空闲存活时间,即当线程池中的线程数量大于 corePoolSize 时,多余的线程在空闲状态下可以存活的最大时间。

作用

  • 如果一个线程在空闲状态下超过了 keepAliveTime,它会被销毁,从而减少线程池的资源占用。
  • 该参数仅对非核心线程有效,核心线程默认不会被销毁(除非设置了 allowCoreThreadTimeOuttrue)。
unit

含义keepAliveTime 参数的时间单位,用于指定 keepAliveTime 的时间单位。

常见的时间单位有 TimeUnit.SECONDS(秒)、TimeUnit.MILLISECONDS(毫秒)、TimeUnit.MINUTES(分钟)等。

workQueue

含义:任务队列,用于存储等待执行的任务。

作用

  • 当线程池中的线程数量达到 corePoolSize 时,新提交的任务会被放入任务队列中等待执行。
  • 如果任务队列已满且线程池中的线程数量小于 maximumPoolSize,线程池会创建新的线程来处理任务。
  • 如果大于了maximumPoolSize,会根据对应的拒绝策略拒绝线程

常见任务队列类型

  • ArrayBlockingQueue:基于数组的有界阻塞队列,需要指定队列容量。
  • LinkedBlockingQueue:基于链表的无界阻塞队列(实际上有最大容量限制,但通常很大)。
  • SynchronousQueue:不存储任务的阻塞队列,每个插入操作必须等待一个移除操作,反之亦然。
  • PriorityBlockingQueue:支持优先级排序的无界阻塞队列。
threadFactory

含义:线程工厂,用于创建新线程。

作用

  • 默认情况下,线程池会使用 Executors.defaultThreadFactory() 创建线程,但可以通过自定义 ThreadFactory 来设置线程的名称、优先级等属性。

  • 一般不会改变,直接用Executors.defaultThreadFactory();

handler

含义:拒绝策略,用于处理线程池拒绝任务的情况。

作用

  • 当线程池中的线程数量达到 maximumPoolSize 且任务队列已满时,再有新任务提交,线程池会调用拒绝策略来处理这些任务。

四大拒绝策略
  • AbortPolicy:默认拒绝策略,抛出 RejectedExecutionException 异常。

  • CallerRunsPolicy:由提交任务的线程(调用者线程)来执行任务。

  • DiscardPolicy:直接丢弃任务,不抛出异常。

  • DiscardOldestPolicy:丢弃队列中最老的任务(即队列头部的任务),然后尝试将新任务加入队列。

扩展:最大线程该如何定义?

根据具体任务类型cpu密集型和io密集型来确定最大线程,是优化线程池性能的关键步骤

CPU密集型任务

对于CPU密集型任务,线程池中的线程主要在执行计算操作,CPU利用率较高。因此,线程数量应与CPU核心数相匹配,以避免过多的上下文切换和资源竞争。

建议的最大线程数

  • 核心线程数(corePoolSize:设置为CPU核心数。

  • 最大线程数(maximumPoolSize:设置为CPU核心数的1.5到2倍。

I/O密集型任务

对于I/O密集型任务,线程大部分时间都在等待I/O操作完成,CPU利用率较低。因此,可以设置更多的线程来提高系统的并发性能。

建议的最大线程数

  • 核心线程数(corePoolSize:设置为CPU核心数的2到4倍。

  • 最大线程数(maximumPoolSize:设置为CPU核心数的数倍,甚至更高(如10倍)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值