热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

细说线程池入门篇!!!

什么是线程池?在Java中,如果每个请求到达后就创建一个线程,创建和销毁线程花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用


什么是线程池?
在Java中,如果每个请求到达后就创建一个线程,创建和销毁线程花费的时间和消耗的系统资源都相当大,甚至可能要比在处理实际的用户请求的时间和资源要多的多。

如果在一个JVM里创建太多的线程,可能会是系统由于过度消耗内存或者CPU时间片切换过度而导致系统资源不足。

为了解决这个问题,就有了线程池的概念。线程池的核心逻辑是提前创建好若干个线程,放在一个容器中。如果没有任务需要处理,则将任务直接分配给线程池的线程来执行就行,任务处理完以后,这个不会被销毁,而是等待后续分配任务。同时通过线程池来重复管理线程还可以避免创建大量线程增加开销。

线程池的优势

合理的使用线程池,可以带来如下好处:

1,降低创建线程和销毁线程的性能开销。

2,提高响应速度,当有新任务需要执行时,不需要等待线程创建就可以立马执行。

3,合理的设置线程池的大小,可以避免因为线程数量超过硬件资源瓶颈带来的问题。

常用线程池

JDK自带的线程池(Executors工厂类或者ThreadPoolExector)

Spring封装的线程池

JDK中提供的线程池API的使用

既然是搞Java开发,线程池这个名词肯定不陌生了,或多或少有点点了解,但是实话实说,能真正的在工作中,尤其是写业务代码中使用过线程池的肯定不多,但是绝对不影响咱们学习线程池,说不定那天你在工作中就用了呢,再说面试中也是常问题目之一,既然这样,那么咱们还是很有必要对线程的原理要有着深层次的理解。

要了解一个技术,我们仍然是从使用开始,JDK为我们提供了几种不同线程池实现。我们先通过一个简单的案例来引入线程池的基本使用。

运行结果:

JDK中自带的线程池API

为了方便于大家对于线程池的使用,在Executors里面提供了几个线程池的工厂方法,这样对于很多新手就不需要了解太多关于线程池的知识了,只需要直接使用Executors的工厂方法,就可以创建线程池了。下面介绍常用几个方式:

newFixedThreadPool

该方法返回一个固定数量的线程池,线程数量不变,当有一个任务提交时,如线程池中存在空闲线程,则立即执行任务,如果没有空闲线程,则会被暂缓存放在一个任务队列中(容器中),等待由空闲线程去执行。

核心线程数和最大线程数都是指定值,也就是说当线程池中的线程数超过核心线程数后,任务都会被放到阻塞队列中。另外 keepAliveTime 为 0,也就是超出核心线程数量以外的线程空余存活时间,

而这里选用的阻塞队列是LinkedBlockingQueue,使用的是默认容量Integer.MAX_VALUE,相当于没有上限。

这个线程池执行任务的流程如下:

  1. 线程数少于核心线程数,也就是设置的线程数时,新建线程执行任务

  2. 线程数等于核心线程数后,将任务加入阻塞队列

  3. 由于队列容量非常大,可以一直添加

  4. 执行完任务的线程反复去队列中取任务执行

用途

newFixedThreadPool用于负载比较大的服务器,为了资源的合理利用,需要限制当前线程数量

newSingleThreadExecutor

创建一个线程的线程池(单个线程的线程池)。如果存在空闲则执行任务,否则将任务暂缓存放在任务队列中。

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

newCachedThreadPool

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程; 并且没有核心线程,非核心线程数无上限,但是每个空闲的时间只有 60 秒,超过后就会被回收。

它的执行流程如下:

  1. 没有核心线程,直接向 SynchronousQueue 中提交任务

  2. 如果有空闲线程,就去取出任务执行;如果没有空闲线程,就新建一个

  3. 执行完任务的线程有 60 秒生存时间,如果在这个时间内可以接到新任务,就可以继续活下去,否则就被回收

newScheduledThreadPool

创建一个可以指定线程的数量大小的线程池,同时这个线程池还带有延迟和周期性执行任务的功能,类似于定时器,很多框架中喜欢该方法来实现心跳检测。

ThreadpoolExecutor

上面提到的四种线程池的构建,都是基于 ThreadpoolExecutor来构建的,小伙伴们打起精神来了,接下来将一起了解一下面试官最喜欢问到的一道面试题“请简单说下你知道的线程池和ThreadPoolThread有哪些构造参数”:

Executors.newFixedThreadPool(int nThreads);源码部分:

ThreadpoolExecutor有多个重载的构造方法,我们可以基于它最完整的构造方法来分析先来解释一下每个参数的作用,稍后我们在分析源码的过程中再来详细了解参数的意义。

线程池参数含义解释

int corePoolSize, //核心线程数量
int maximumPoolSize, //最大线程数
long keepAliveTime, //超时时间,超出核心线程数量以外的线程空余存活时间
TimeUnit unit, //存活时间单位
BlockingQueue workQueue, //保存执行任务的队列
ThreadFactory threadFactory,//创建新线程使用的工厂
RejectedExecutionHandler handler //当任务无法执行的时候的处理方式

这个地方有很多小伙伴一起聊过,线程池初始化以后做了什么事情,线程池初始化时是没有创建线程的,线程池里的线程的初始化与其他线程一样,但是在完成任务以后,该线程不会自行销毁,而是以挂起的状态返回到线程池。直到应用程序再次向线程池发出请求时,线程池里挂起的线程就会再度激活执行任务。这样既节省了建立线程所造成的性能损耗,也可以让多个任务反复重用同一线程,从而在应用程序生存期内节约大量开销。

Java 线程池 8 大拒绝策略,面试必问!

为什么阿里巴巴要禁用 Executors 创建线程池?

面试官:为什么Java线程没有Running状态?

Java多线程实战:多线程方法详解



推荐阅读
  • Spring框架《一》简介
    Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 网卡工作原理及网络知识分享
    本文介绍了网卡的工作原理,包括CSMA/CD、ARP欺骗等网络知识。网卡是负责整台计算机的网络通信,没有它,计算机将成为信息孤岛。文章通过一个对话的形式,生动形象地讲述了网卡的工作原理,并介绍了集线器Hub时代的网络构成。对于想学习网络知识的读者来说,本文是一篇不错的参考资料。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • Centos下安装memcached+memcached教程
    本文介绍了在Centos下安装memcached和使用memcached的教程,详细解释了memcached的工作原理,包括缓存数据和对象、减少数据库读取次数、提高网站速度等。同时,还对memcached的快速和高效率进行了解释,与传统的文件型数据库相比,memcached作为一个内存型数据库,具有更高的读取速度。 ... [详细]
  • 本文介绍了在Android开发中使用软引用和弱引用的应用。如果一个对象只具有软引用,那么只有在内存不够的情况下才会被回收,可以用来实现内存敏感的高速缓存;而如果一个对象只具有弱引用,不管内存是否足够,都会被垃圾回收器回收。软引用和弱引用还可以与引用队列联合使用,当被引用的对象被回收时,会将引用加入到关联的引用队列中。软引用和弱引用的根本区别在于生命周期的长短,弱引用的对象可能随时被回收,而软引用的对象只有在内存不够时才会被回收。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
author-avatar
你的依靠isme
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有