当前位置: 首页 > news >正文

多线程-线程池

为什么要使用线程池

      

在Java中使用线程池的主要原因有以下几点:

  1. 提高性能:使用线程池可以减少线程的创建和销毁过程的开销。线程的创建和销毁是比较昂贵的操作,如果每次需要执行任务时都创建一个新线程,会造成系统资源的浪费。而线程池可以在程序启动时就创建一定数量的线程,然后重复使用这些线程来执行多个任务。这样可以减少线程创建和销毁的次数,提高系统的性能。

  2. 控制并发数量:线程池可以控制同时执行的任务数量。通过设置线程池的大小,可以限制并发执行的线程数量,避免系统资源被过度占用,导致整个系统的性能下降。

  3. 提供可管理的线程:线程池提供了一种管理和监视线程的机制。通过使用线程池,可以方便地对线程进行管理,比如动态调整线程池大小、监控线程的运行状态等。

  4. 提供线程复用:线程池可以重复利用已有的线程来执行任务,避免了线程的创建和销毁过程,提高了系统的效率。

  5. 提供任务排队机制:线程池可以提供一个任务队列,用于存放等待执行的任务。当线程池中的线程都在执行任务时,新的任务可以被放入队列中,等待线程空闲时执行。这样可以避免任务因为没有可用线程而被丢弃或者阻塞。

常用的几种线程池以及其中的工作原理

     

在Java中,常用的几种线程池有以下几种:

  1. FixedThreadPool:固定大小的线程池,线程数量固定不变,适合执行长期的任务。如果所有线程都处于繁忙状态,新任务将在队列中等待。

  2. CachedThreadPool:可缓存的线程池,线程数量不固定,适合执行大量的短期任务。如果线程池中有可用的线程,就会重用它;如果没有可用线程,就会创建一个新线程。当线程闲置时间超过60秒时,线程将被终止并从池中移出。

  3. SingleThreadPool:单线程的线程池,只会创建一个线程来执行任务。适合需要顺序执行任务的场景。

  4. ScheduledThreadPool:用于延时或定时执行任务的线程池。可以按照指定的周期来执行任务,或者在指定的延迟时间之后执行任务。

线程池的工作原理如下:

  1. 创建线程池时,会初始化一定数量的线程,这些线程会一直存在,等待任务的到来。

  2. 当有任务提交给线程池时,会从线程池中选择一个空闲的线程来执行任务。如果没有空闲线程,任务将被添加到线程池的任务队列中等待执行。

  3. 如果任务队列已满,且线程池中的线程数未达到线程池的最大线程数限制,线程池会创建一个新的线程来执行任务。

  4. 当线程执行完任务后,会检查任务队列中是否还有等待执行的任务。如果有,继续从任务队列中选择任务来执行。如果没有,线程将进入空闲状态,等待下一个任务的到来。

  5. 当线程池不再接收新的任务时,可以调用shutdown()方法来关闭线程池。关闭线程池后,线程池中的线程会等待任务队列中的任务执行完毕后退出。

线程池启动线程 submit()和 execute()方法有什么不同

      submit()方法和execute()方法都是用于向线程池提交任务的方法,但是它们有一些不同之处:

  1. 返回值不同:submit()方法返回一个Future对象,可以用来获取任务的执行结果或取消任务;而execute()方法没有返回值。

  2. 异常处理不同:submit()方法会捕获任务执行过程中的异常,并将其封装到Future对象中,通过调用Future对象的get()方法可以获取到异常信息;而execute()方法不会捕获任务执行过程中的异常,如果任务发生异常,线程池会将异常抛出到控制台。

  3. 可接收的参数类型不同:submit()方法可以接收Callable对象、Runnable对象或Runnable实现类的对象作为参数;而execute()方法只能接收Runnable对象或Runnable实现类的对象作为参数。

实例

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ScheduledThreadPoolExample {public static void main(String[] args) {// 创建ScheduledThreadPool,指定线程池中的线程数为3ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);// 定义一个Runnable任务Runnable task = new Runnable() {@Overridepublic void run() {System.out.println("Task executed at " + System.currentTimeMillis());}};// 使用scheduledExecutorService调度任务,在延迟1秒后开始执行任务,并且每隔3秒重复执行scheduledExecutorService.scheduleAtFixedRate(task, 1, 3, TimeUnit.SECONDS);// 主线程休眠10秒,以便观察任务的执行try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}// 关闭ScheduledThreadPoolscheduledExecutorService.shutdown();}
}

在这个示例中,我们首先创建了一个ScheduledThreadPool,指定线程池中的线程数为3。

然后,我们定义了一个Runnable任务,该任务将在执行时打印当前时间。

接下来,我们使用scheduledExecutorService.scheduleAtFixedRate()方法来调度任务。这个方法接受四个参数:任务、延迟时间、重复间隔和时间单位。在这个例子中,我们将任务延迟1秒后开始执行,并且每隔3秒重复执行一次。

最后,我们让主线程休眠10秒,以便观察任务的执行。然后,我们调用scheduledExecutorService.shutdown()方法来关闭ScheduledThreadPool。

 总结

线程池的主要优点如下:

  1. 重用线程:线程池可以重用已经创建的线程,避免了频繁地创建和销毁线程的开销。
  2. 控制并发数量:线程池可以限制并发线程的数量,防止过多的线程导致系统资源的浪费或者负载过重。
  3. 提高响应速度:线程池可以预先创建一组线程,当任务到达时可以立即执行,而不需要等待线程的创建过程,从而提高系统响应速度。
  4. 提供线程管理和监控功能:线程池可以提供一些管理和监控的方法,用于管理和监控线程的状态和运行情况。

使用线程池时需要注意以下几点:

  1. 线程池大小的选择:线程池的大小需要根据系统的负载和资源情况进行选择,太小会导致线程不足,任务无法及时处理,太大会导致资源浪费和负载过重。
  2. 线程池的关闭:在程序结束时需要正确地关闭线程池,释放资源,避免资源泄漏。
  3. 任务的提交方式:任务的提交可以采用不同的方式,如同步提交、异步提交等,需要根据实际需要进行选择。
  4. 错误处理机制:线程池需要有相应的错误处理机制,处理任务执行过程中的异常情况。

    

相关文章:

  • Spring Boot中如何查询PGSQL分表后的数据
  • Pytorch 笔记
  • Linux入门攻坚——23、DNS和BIND基础入门2
  • 微信小程序开发(持续更新)
  • 实时合成 1 秒频订单簿快照:DolphinDB INSIGHT 行情插件与订单簿引擎应用
  • FaceChain-FACT:开源10秒写真生成,复用海量LoRa风格,基模友好型写真应用
  • 【链表】Leetcode 82. 删除排序链表中的重复元素 II【中等】
  • JavaScript日期与时间处理的艺术
  • webshell工具-冰蝎流量特征和加密方式
  • VUE3学习第一篇:启动ruoyi
  • 计算机网络-BGP基础概念
  • 算法之堆排序
  • 量子密钥分发系统基础器件(一):光纤干涉仪
  • C#算数运算符
  • HBase安装
  • [LeetCode] Wiggle Sort
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • Facebook AccountKit 接入的坑点
  • httpie使用详解
  • HTTP中GET与POST的区别 99%的错误认识
  • Java 多线程编程之:notify 和 wait 用法
  • java8 Stream Pipelines 浅析
  • javascript数组去重/查找/插入/删除
  • JAVA并发编程--1.基础概念
  • leetcode388. Longest Absolute File Path
  • MySQL的数据类型
  • Node 版本管理
  • Shadow DOM 内部构造及如何构建独立组件
  • 不上全站https的网站你们就等着被恶心死吧
  • 从零开始的无人驾驶 1
  • 驱动程序原理
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #HarmonyOS:基础语法
  • (+4)2.2UML建模图
  • (175)FPGA门控时钟技术
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (补)B+树一些思想
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (分类)KNN算法- 参数调优
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (精确度,召回率,真阳性,假阳性)ACC、敏感性、特异性等 ROC指标
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (未解决)macOS matplotlib 中文是方框
  • (循环依赖问题)学习spring的第九天
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (译)计算距离、方位和更多经纬度之间的点
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)c++ std::pair 与 std::make