什么是线程池?

线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务的执行交由线程池来管理。

如果每个请求都创建一个线程去处理,那么服务器的资源很快就会被耗尽,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

为什么要使用线程池?

创建线程和销毁线程的花销是比较大的,这些时间有可能比处理业务的时间还要长。这样频繁的创建线程和销毁线程,再加上业务工作线程,消耗系统资源的时间,可能导致系统资源不足。(我们可以把创建和销毁的线程的过程去掉)

线程池有什么作用?

线程池作用就是限制系统中执行线程的数量。

1、提高效率 创建好一定数量的线程放在池中,等需要使用的时候就从池中拿一个,这要比需要的时候创建一个线程对象要快的多。

2、方便管理 可以编写线程池管理代码对池中的线程同一进行管理,比如说启动时有该程序创建100个线程,每当有请求的时候,就分配一个线程去工作,如果刚好并发有101个请求,那多出的这一个请求可以排队等候,避免因无休止的创建线程导致系统崩溃。

说说几种常见的线程池及使用场景

1、newSingleThreadExecutor

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

2、newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

3、newCachedThreadPool

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

4、newScheduledThreadPool

创建一个定长线程池,支持定时及周期性任务执行。

线程池中的几种重要的参数

corePoolSize就是线程池中的核心线程数量,这几个核心线程,只是在没有用的时候,也不会被回收

maximumPoolSize就是线程池中可以容纳的最大线程的数量

keepAliveTime,就是线程池中除了核心线程之外的其他的最长可以保留的时间,因为在线程池中,除了核心线程即使在无任务的情况下也不能被清                                除,其余的都是有存活时间的,意思就是非核心线程可以保留的最长的空闲时间,

util,就是计算这个时间的一个单位。

workQueue,就是等待队列,任务可以储存在任务队列中等待被执行,执行的是FIFIO原则(先进先出)。

threadFactory,就是创建线程的线程工厂。

handler,是一种拒绝策略,我们可以在任务满了之后,拒绝执行某些任务。

说说线程池的拒绝策略

当请求任务不断的过来,而系统此时又处理不过来的时候,我们需要采取的策略是拒绝服务。RejectedExecutionHandler接口提供了拒绝任务处理的自定义方法的机会。在ThreadPoolExecutor中已经包含四种处理策略。

  • AbortPolicy策略:该策略会直接抛出异常,阻止系统正常工作。

  • CallerRunsPolicy 策略:只要线程池未关闭,该策略直接在调用者线程中,运行当前的被丢弃的任务。

  • DiscardOleddestPolicy策略: 该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。

  • DiscardPolicy策略:该策略默默的丢弃无法处理的任务,不予任何处理。

除了JDK默认提供的四种拒绝策略,我们可以根据自己的业务需求去自定义拒绝策略,自定义的方式很简单,直接实现RejectedExecutionHandler接口即可。

execute和submit的区别?

在前面的讲解中,我们执行任务是用的execute方法,除了execute方法,还有一个submit方法也可以执行我们提交的任务。

这两个方法有什么区别呢?分别适用于在什么场景下呢?我们来做一个简单的分析。

execute适用于不需要关注返回值的场景,只需要将线程丢到线程池中去执行就可以了。

submit方法适用于需要关注返回值的场景

五种线程池的使用场景

  • newSingleThreadExecutor:一个单线程的线程池,可以用于需要保证顺序执行的场景,并且只有一个线程在执行。

  • newFixedThreadPool:一个固定大小的线程池,可以用于已知并发压力的情况下,对线程数做限制。

  • newCachedThreadPool:一个可以无限扩大的线程池,比较适合处理执行时间比较小的任务。

  • newScheduledThreadPool:可以延时启动,定时启动的线程池,适用于需要多个后台线程执行周期任务的场景。

  • newWorkStealingPool:一个拥有多个任务队列的线程池,可以减少连接数,创建当前可用cpu数量的线程来并行执行。

线程池的关闭

关闭线程池可以调用shutdownNow和shutdown两个方法来实现

shutdownNow:对正在执行的任务全部发出interrupt(),停止执行,对还未开始执行的任务全部取消,并且返回还没开始的任务列表。

shutdown:当我们调用shutdown后,线程池将不再接受新的任务,但也不会去强制终止已经提交或者正在执行中的任务。

初始化线程池时线程数的选择

如果任务是IO密集型,一般线程数需要设置2倍CPU数以上,以此来尽量利用CPU资源。

如果任务是CPU密集型,一般线程数量只需要设置CPU数加1即可,更多的线程数也只能增加上下文切换,不能增加CPU利用率。

上述只是一个基本思想,如果真的需要精确的控制,还是需要上线以后观察线程池中线程数量跟队列的情况来定。

线程池都有哪几种工作队列

1、ArrayBlockingQueue

是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。

2、LinkedBlockingQueue

一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列

3、SynchronousQueue

一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。

4、PriorityBlockingQueue

一个具有优先级的无限阻塞队列。

java线程池 面试题(精简)的更多相关文章

  1. 面试题-关于Java线程池一篇文章就够了

    在Java面试中,线程池相关知识,虽不能说是必问提,但出现的频次也是非常高的.同时又鉴于公众号"程序新视界"的读者后台留言让写一篇关于Java线程池的文章,于是就有本篇内容,本篇将 ...

  2. 面试题:四种Java线程池用法解析 !=!=未看

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? 1 2 3 4 5 6 7 8 new Thread(new Runnable() {     @Override ...

  3. Java线程经典面试题

    53道Java线程面试题 下面是Java线程相关的热门面试题,你可以用它来好好准备面试. 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序 ...

  4. Java 线程池比较

    小结: 1. 高级面试题总结—线程池还能这么玩? - 这个时代,作为程序员可能要学习小程序 - CSDN博客https://blog.csdn.net/androidstarjack/article/ ...

  5. 聊聊面试中的 Java 线程池

    ​背景 关于 Java 的线程池我想大家肯定不会陌生,在工作中或者自己平时的学习中多多少少都会用到,那你真的有了解过底层的实现原理吗?还是说只停留在用的阶段呢?而且关于 Java 线程池也是在面试中的 ...

  6. 面试必备:Java线程池解析

    前言 掌握线程池是后端程序员的基本要求,相信大家求职面试过程中,几乎都会被问到有关于线程池的问题.我在网上搜集了几道经典的线程池面试题,并以此为切入点,谈谈我对线程池的理解.如果有哪里理解不正确,非常 ...

  7. Java线程池实现

    电脑的CPU资源是有限的,任务的处理速度与线程数量之间并不是正相关.当线程数量过多,CPU要频繁的在不同线程切换,反而会引起处理性能的下降.线程池中最大的线程数,是考虑多种因素来事先设定的,比如硬件的 ...

  8. Java 线程池框架核心代码分析--转

    原文地址:http://www.codeceo.com/article/java-thread-pool-kernal.html 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和 ...

  9. Java线程池使用说明

    Java线程池使用说明 转自:http://blog.csdn.net/sd0902/article/details/8395677 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极 ...

随机推荐

  1. 小哈学python----一行代码输出特定字符"Love"拼成的心形

    print('\n'.join([''.join([('Love'[(x-y) % len('Love')] if ((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2* ...

  2. Selenium执行完毕未关闭chromedriver/geckodriver进程的解决办法(java版+python版)

    selenium操作chrome浏览器需要有ChromeDriver驱动来协助.webdriver中关浏览器关闭有两个方法,一个叫quit,一个叫close. 1 /** 2 * Close the ...

  3. Java基础00-内部类23

    1. 内部类 内部类 1.1 内部类概述 代码示例: 1.2 成员内部类 代码示例: 创建一个成员内部类:定义时没有小括号是因为类是没有形参的.在类的成员位置,就是成员内部类了 创建测试类:这里发现不 ...

  4. Odoo ORM研究2 - BaseModel中的常用方法分析

    今天继续研究ORM的BaseModel,昨天研究了一下所有常用属性的具体用法,那么今天研究一下BaseModel中一些常用的方法,我们学会它们并灵活的应用它们,可以为我们开发解决很多的问题. odoo ...

  5. 【经典结构】单例模式Singleton

    单例模式Singleton 1.含义 单例模式:即一个类只能创建一个实例. 只有一个实例 --> 不可以从类外new对象 --> 构造器私有化private --> 从类里创建实例: ...

  6. Album++:分布式事务专辑-基础概念

    (一)基础概念:↓ ↓ ↓ 1.1)什么是事务 什么是事务?举个生活中的例子:你去小卖铺买东西,"一手交钱,一手交货"就是一个事务的例子,交钱和交货必 须全部成功, 事务才算成功, ...

  7. debian 9 pycharm安装

    官网下载PyCharm的tar.gz格式 使用命令进行解压:tar -xvzf pycharm.tar.gz 解压后将pycharm文件夹移动到/usr/local/lib/目录下 进入pycharm ...

  8. Python基础之创建文件夹与删除文件夹。

    参考链接:https://blog.csdn.net/weixin_43826242/article/details/87101436 创建目录结构 # 创建文件目录结构 def create_fol ...

  9. Maven之--安装nexus 私服

    开始搜索下载了,nexus3.19版本,下来之后,建立一个maven 骨架过程 quickstart,提示没有lgf4j依赖和和maven插件都没有,开始搜索什么原因,猜想是nexus没有索引,右搜索 ...

  10. K8s之Prometheus监控

    目录 容器监控与报警 Prometheus prometheus简介 prometheus系统架构 prometheus 安装方式 容器方式安装prometheus operator部署 克隆项目 创 ...