线程池参数-SpringBoot配置线程池

先线程池有几个核心的参数概念:

  1. 核心线程数(corePoolSize)

    线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。这里的最小线程数量即是corePoolSize。任务提交到线程池后,首先会检查当前线程数是否达到了corePoolSize,如果没有达到的话,则会创建一个新线程来处理这个任务。

  2. 最大线程数(maximumPoolSize)

    当前线程数达到corePoolSize后,如果继续有任务被提交到线程池,会将任务缓存到工作队列(后面会介绍)中。如果队列也已满,则会去创建一个新线程来出来这个处理。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。

  3. 活跃时间/空闲线程存活时间(keepAliveTime)

    一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定

  4. 空闲线程存活时间的单位(unit)

    是指空闲线程存活时间的单位。keepAliveTime的计量单位。枚举类型TimeUnit类。线程空闲时间的单位,可以是秒、毫秒等。

  5. 阻塞队列/线程工作队列(workQueue)

    1. ArrayBlockingQueue FIFO有界阻塞队列
    2. LinkedBlockingQueue FIFO无限队列
    3. SynchronousQueue不缓存任务的阻塞队列
    4. PriorityBlockingQueue具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
  6. 线程工厂(threadFactory)

    创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等,一般使用默认的ThreadFactory即可。

  7. 超出线程数和工作队列时候的任务请求处理策略/拒绝策略(handler)

    当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制,这时如果有新任务提交进来,该如何处理呢。对新任务的处理策略,可以是抛出异常、丢弃任务等。这里的拒绝策略,就是解决这个问题的,jdk中提供了4中拒绝策略:

    • 策略1:ThreadPoolExecutor.AbortPolicy(默认)拒绝执行
    • 策略2:ThreadPoolExecutor.CallerRunsPolicy调用 execute 方法的线程本身运行任务
    • 策略3:ThreadPoolExecutor.DiscardOldestPolicy执行程序未关闭,则删除工作队列头部的任务
    • 策略4:ThreadPoolExecutor.DiscardPolicy无法执行的任务被简单地删除
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
原生使用
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 10, 30, 
                                                           TimeUnit.SECONDS, 
                                                           new ArrayBlockingQueue<>(4),
                                                           Executors.defaultThreadFactory(), 
                                                           new ThreadPoolExecutor.DiscardOldestPolicy());

spring使用

配置文件
@Configuration
@EnableAsync
public class ThreadPoolConfig {
   /**
    * 下面的配置是配置Springboot的@Async注解所用的线程池
    */
   @Bean("taskExecutor")
   public Executor taskExecutor() {
       ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
       // 设置线程池核心容量
       executor.setCorePoolSize(4);
       // 设置线程池最大容量
       executor.setMaxPoolSize(8);
       // 设置任务队列长度
       executor.setQueueCapacity(200);
       // 设置线程超时时间
       executor.setKeepAliveSeconds(60);
       // 设置线程名称前缀
       executor.setThreadNamePrefix("xyjAsyncPool-");
       // 设置任务丢弃后的处理策略,当poolSize已达到maxPoolSize,如何处理新任务(是拒绝还是交由其它线程处理)
       // CallerRunsPolicy: 不在新线程中执行任务,而是由调用者所在的线程来执
       executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
       executor.initialize();
       return executor;
   }
}

配置测试接口及其实现类
public interface TestAsync {
   void doAsync();
}

@Service
@Slf4j
public class TestAsyncImpl implements TestAsync {
   @Override
   //使用@Async,并将前面的注册的bean,填写到Async的value中
   @Async("taskExecutor")
   public void doAsync() {
       log.info("== async start==");
       log.info("线程{}执行代码逻辑",Thread.currentThread().getName());
       log.info("== async end==");
   }
}

测试
@SpringBootTest
public class AsyncTest {
   //引用类
   @Autowired
   private TestAsync testAsync;

   @Test
   void test(){
       for (int i = 0; i < 10; i++) {
           testAsync.doAsync();
       }

   }
}
结果
2023-01-29 16:47:12.491  INFO 13332 --- [ taskExecutor-1] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.491  INFO 13332 --- [ taskExecutor-3] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.493  INFO 13332 --- [ taskExecutor-5] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.493  INFO 13332 --- [ taskExecutor-6] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.493  INFO 13332 --- [ taskExecutor-1] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.501  INFO 13332 --- [ taskExecutor-9] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.501  INFO 13332 --- [taskExecutor-10] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.500  INFO 13332 --- [ taskExecutor-7] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.502  INFO 13332 --- [ taskExecutor-8] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.500  INFO 13332 --- [ taskExecutor-7] c.w.a.service.async.impl.TestAsyncImpl   : == async start==
2023-01-29 16:47:12.502  INFO 13332 --- [ taskExecutor-6] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-6执行代码逻辑
2023-01-29 16:47:12.501  INFO 13332 --- [ taskExecutor-8] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-8执行代码逻辑
2023-01-29 16:47:12.503  INFO 13332 --- [ taskExecutor-5] c.w.a.service.async.impl.TestAsyncImpl   : == async end==
2023-01-29 16:47:12.492  INFO 13332 --- [ taskExecutor-9] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-9执行代码逻辑
2023-01-29 16:47:12.503  INFO 13332 --- [ taskExecutor-2] c.w.a.service.async.impl.TestAsyncImpl   : == async end==
2023-01-29 16:47:12.503  INFO 13332 --- [ taskExecutor-7] c.w.a.service.async.impl.TestAsyncImpl   : == async end==
2023-01-29 16:47:12.501  INFO 13332 --- [ taskExecutor-9] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-9执行代码逻辑
2023-01-29 16:47:12.492  INFO 13332 --- [ taskExecutor-1] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-1执行代码逻辑
2023-01-29 16:47:12.506  INFO 13332 --- [ taskExecutor-1] c.w.a.service.async.impl.TestAsyncImpl   : == async end==
2023-01-29 16:47:12.506  INFO 13332 --- [ taskExecutor-9] c.w.a.service.async.impl.TestAsyncImpl   : == async end==
2023-01-29 16:47:12.493  INFO 13332 --- [ taskExecutor-3] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-3执行代码逻辑
2023-01-29 16:47:12.501  INFO 13332 --- [taskExecutor-10] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-10执行代码逻辑
2023-01-29 16:47:12.506  INFO 13332 --- [ taskExecutor-3] c.w.a.service.async.impl.TestAsyncImpl   : == async end==
2023-01-29 16:47:12.506  INFO 13332 --- [taskExecutor-10] c.w.a.service.async.impl.TestAsyncImpl   : == async end==
2023-01-29 16:47:12.502  INFO 13332 --- [ taskExecutor-8] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-8执行代码逻辑
2023-01-29 16:47:12.506  INFO 13332 --- [ taskExecutor-8] c.w.a.service.async.impl.TestAsyncImpl   : == async end==
2023-01-29 16:47:12.502  INFO 13332 --- [ taskExecutor-7] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-7执行代码逻辑
2023-01-29 16:47:12.508  INFO 13332 --- [ taskExecutor-7] c.w.a.service.async.impl.TestAsyncImpl   : == async end==
2023-01-29 16:47:12.493  INFO 13332 --- [ taskExecutor-4] c.w.a.service.async.impl.TestAsyncImpl   : 线程taskExecutor-4执行代码逻辑
2023-01-29 16:47:12.508  INFO 13332 --- [ taskExecutor-4] c.w.a.service.async.impl.TestAsyncImpl   : == async end==


<think>好的,我现在需要回答用户关于YOLOv11-seg和YOLOv11-detect之间的区别,特别是功能实现方面的差异。首先,我需要回忆YOLO系列模型的基本知识,尤其是分割(segmentation)和检测(detection)任务的不同之处。 用户提到的YOLOv11-seg和YOLOv11-detect,可能是指同一版本YOLO的不同变体,分别用于分割和检测。检测任务通常是识别图像中的物体并给出边界框和类别,而分割任务则需要更精确的像素级分类,即每个像素属于哪个物体或类别。因此,两者的模型结构可能在输出层或头部设计上有所不同。 接下来,我需要参考用户提供的引用内容。引用[1]提到了导出YOLO模型为ONNX格式,可能涉及模型的结构和输出。引用[2]讨论了使用RKNN进行部署,说明两者都需要优化以适应硬件,但具体的结构差异可能影响部署时的处理方式。例如,分割模型可能输出更多的数据(如掩膜),需要不同的后处理步骤。 然后,我需要详细比较两者的功能实现。检测模型通常输出边界框、类别置信度和类别概率,而分割模型除此之外还会输出每个实例的掩膜。因此,YOLOv11-seg可能在检测头的基础上添加了掩膜预测分支,或者使用不同的解码方式。例如,YOLO的实例分割模型如YOLACT或YOLOv5-seg,通常会在检测的基础上通过原型掩膜和系数矩阵生成实例分割结果。 另外,训练数据方面,检测模型需要边界框标注,而分割模型需要像素级的掩膜标注。这可能导致两者的训练过程和损失函数不同,分割模型的损失可能包括掩膜的交叉熵损失或Dice损失等。 用户还可能关心性能和应用场景。分割模型由于需要处理更多数据,可能计算量更大,推理速度较慢,适合需要精确轮廓的应用,如医学图像分析或自动驾驶中的场景理解。而检测模型更适用于实时性要求高的场景,如视频监控或移动端应用。 最后,我需要确保回答结构清晰,符合用户要求,使用正确的LaTeX格式,并生成相关问题。同时,引用用户提供的两个引用,但注意引用内容是否直接相关。引用[2]提到的是姿态估计的部署,可能与分割和检测的差异无直接关系,但可以说明不同任务模型在部署时的优化需求类似。需要确认引用是否适用于当前问题,或是否需要调整引用标注。</think>### YOLOv11-seg与YOLOv11-detect的功能实现差异 YOLOv11-seg(实例分割模型)和YOLOv11-detect(目标检测模型)在功能实现上的核心区别在于**任务目标与输出形式**。以下是具体分析: --- #### 1. **任务目标** - **YOLOv11-detect** 专注于**目标检测**,即定位图像中的物体并输出其边界框(Bounding Box)、类别标签及置信度。例如,在图像中标注“狗”的位置和类别。 **数学表示**:输出形式为$B = (x, y, w, h, c)$,其中$(x, y)$为中心坐标,$(w, h)$为宽高,$c$为类别概率。 - **YOLOv11-seg** 在检测基础上增加**实例分割**功能,需额外生成每个物体的像素级掩膜(Mask)。例如,在标注“狗”的边界框时,还需精确标记其轮廓的每个像素[^1]。 **数学表示**:输出包含掩膜矩阵$M \in \mathbb{R}^{H \times W}$,其中$H \times W$为图像分辨率,值表示像素是否属于目标。 --- #### 2. **模型结构差异** - **检测头部(Detection Head)** - **YOLOv11-detect**:通过卷积层直接预测边界框坐标和类别概率。 - **YOLOv11-seg**:在检测头部基础上增加**掩膜预测分支**,通常结合原型掩膜(Prototype Masks)和掩膜系数矩阵生成实例分割结果[^1]。例如: $$M = \sigma(P \cdot C)$$ 其中$P$为原型掩膜,$C$为检测头输出的系数矩阵,$\sigma$为激活函数。 - **后处理** - **YOLOv11-detect**:仅需非极大值抑制(NMS)筛选重叠框。 - **YOLOv11-seg**:需对掩膜进行阈值化和轮廓优化,计算量更大。 --- #### 3. **训练数据与损失函数** - **训练数据** - 检测模型:依赖标注的边界框(COCO等数据集)。 - 分割模型:需额外掩膜标注(如COCO的`segmentation`字段)。 - **损失函数** - 检测模型:边界框损失(如CIoU)、分类损失(交叉熵)。 - 分割模型:需叠加掩膜损失(如Dice Loss或二进制交叉熵)。 --- #### 4. **应用场景与性能** - **YOLOv11-detect** 适用于实时性要求高的场景,如视频监控、自动驾驶中的障碍物检测。 **优点**:推理速度快,资源占用低。 - **YOLOv11-seg** 适合需要精确物体轮廓的任务,如医学图像分析、机器人抓取。 **缺点**:计算复杂度高,需更多显存和算力[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值