Java线程池及相关概念

Java线程池及相关概念

一.线程

二.线程主要作用

三.两种线程模型

四.线程池意义

五.什么时候使用线程池

六.阻塞队列

七.Executors类创建线程池的四种方法

八.线程池五种状态

一.线程
线程调度CPU最小单元(进程是资源分配的最小单元),也叫轻量级进程,可以理解为进程的执行流。创建了一个进程就会创建一个线程(主线程),也就是一个进程至少包含一个线程。

二.线程主要有两个作用
1.提高多核cpu的利用率,提高运行效率

说明:现在的计算机基本都是多处理机多核,一个核同一时间只能执行一个线程,在之前的单核单处理机上,多线程并不是与多处理机多核上的多线程执行相同,多处理机上的多线程执行才是每个线程同时运行在每个处理机的核上,做到了真正的并行执行

2.单独处理耗时长的任务防止主线程阻塞
也就是实现异步与并发,一些场景下对处理业务与用户体验来说,非常重要。需要异步主要是CPU速度与其他耗时操作的速度不匹配(特别是IO操作),假设极端情况让CPU完全等着我们一个一个键入字符,之后再执行自己的任务与操作,是对计算机资源与用户体验的极大浪费与降低。在加载页面时,可以先加载文字,创建一个线程加载图片,就是我们经常看见的文字页面已经出来了,但图片还在转,若等待图片完全加载出来时才显示页面,很容易就会造成页面卡死或用户感觉请求不到的情况,一些用户是难以接受的,用户体验非常不好。

三.两种线程模型
1.用户级线程(ULT)
用户程序实现,不依赖操作系统核心,应用提供创建,同步,调度和管理线程。不需要用户态/核心态切换,速度快。内核对ULT无感知,线程阻塞则进程(包括它的所有线程)阻塞

2.内核级线程(KLT)
系统内核管理线程,内核保存线程的状态和上下文,线程阻塞不会引起进程阻塞。在多处理器系统上,多线程在在多处理器上并行运行。线程的创建,调度和管理由内核完成,效率比ULT慢,比进程快。

JVM中,基本都是使用KLT

Java线程创建依赖于系统内核,通过JVM调用系统库创建内核线程,内核线程与Java-Thread是1:1的映射关系
在这里插入图片描述四.线程池意义:线程是稀缺资源,它的创建与销毁是一个相对偏重且消耗资源的操作,而Java线程依赖于内核线程,创建线程需要进行操作系统状态切换,为避免资源过度消耗设法重用线程执行多个任务。线程池就是一个线程缓存,负责对线程进行统一分配,调度与监控。

五.什么时候使用线程池?

1.单个任务处理时间短
2.需要处理的任务数量很大

线程池优势
1.重用存在的线程,减少线程创建,消亡的开销,提高性能
2.提高响应速度。当任务到达时,任务不需要等待线程创建就能立即执行
3.提高线程的可管理性,可统一分配,调优和监控
4.提供更强大的功能,延时定时线程池。

备注:与数据库连接池优点对比非常相似,可做对比

六.阻塞队列
分有界和无界
在任意时刻,不管并发有多高,永远只有一个线程能够进行队列的入队或者出队操作,是线程安全的
队列满后,只能进行出队操作,入队被阻塞
队列空,只能进行入队操作,出队被阻塞
在这里插入图片描述当队列超过容量时,没有多余的线程来执行任务,便会执行拒绝策略
默认拒绝策略:抛出异常
常用队列的选择
(1)SynchronousQueue:【直接提交的队列】,容量为0,每次插入都必须等待一个任务的删除操作,每次删除也要等待一个任务的插入操作。使用该队列,由于容量为0,其不会真实的保存任务,而是每次都将新任务提交给线程池,如果线程池满了,则直接执行拒绝策略,简单粗暴。

(2)ArrayBlockingQueue:【有界的任务队列,按照先进先出的顺序出队】,该队列的构造方法为public ArrayBlockingQueue(int capacity),初始化时必须设置其容量。当线程池中的实际线程数小于corePoolSize,则优先创建新的线程;如果大于corePoolSize,并且此时恰好没有空闲线程,则优先进入有界队列,队列满了以后,再从队列中出队任务创建线程,直到线程池中的线程数量达到maximumPoolSize。当大maximumPoolSize后,执行拒绝策略。

(3)LinkedBlockingQueue:【无界的任务队列,按照先进先出的顺序出队】,当线程池中的实际线程数小于corePoolSize,则优先创建新的线程;如果大于corePoolSize,并且此时恰好没有空闲线程,只要服务器资源足够多,就会无限制的进入入队操作,直到资源耗尽。所以使用了该任务队列的线程池最大支持线程数为corePoolSize,所以使用该队列的创建线程池的方法一般是corePoolSize和maximumPoolSize相等的newFixedThreadPool。

(4)PriorityBlockingQueue:【优先任务队列,按照任务的优先级出队】,带有任务执行优先级的队列,可以控制任务执行的先后顺序,在确保系统性能的同时,对质量也有了保证。

创建线程池:
操作:用工具类Executors创建线程池,然后给线程池分配任务,最后关闭线程池

七.Executors类创建线程池的四种方法
1.newFixedThreadPool():
创建一个固定大小的线程池,提交一个任务就在线程池中创建一个线程,直到线程数量达到线程池最大限制。线程池一旦到最大就不会再改变,除非有已经开启的线程出现异常,再提交任务时会继续新建线程。这个创建线程池的方法是在实际项目中比较常用的,由于corePoolSize和maximumPoolSize两个参数是相同大小,所以到了线程池最大容量后,如果有任务完成让出占用线程,那么此线程就会一直处于等待状态,而不会消亡,直到下一个任务再次占用该线程。此方法的弊端是:使用无界队列来存放排队任务,当大量任务超过线程池最大容量需要处理时,队列无线增大,使服务器资源迅速耗尽。

2.newCachedThreadPool():创建一个可根据实际情况调整大小的线程池,线程数量不确定,只要有空闲线程空闲时间超过keepAliveTime,就会干掉,再来新任务,先使用空闲线程,若不够,再新建线程。线程池没有最大线程数量限制,所以当大量线程蜂拥而至,会造成资源耗尽。

3.newSingleThreadExecutor():创建一个容量为1的线程池,被提交任务按优先级依次执行。

4.newScheduledThreadPool():创建一个定长线程池,长度为输入参数自定义,支持定时周期任务执行,可根据时间需要在指定时间对线程进行调度。

相关参数
corePoolSize:线程池中的线程数量,超过该数量的空闲线程空闲时间超过keepAliveTime则会被销毁,在该数量内的空闲线程则不会被销毁,在下一个任务来临之前一直处于等待状态。
maximumPoolSize:线程池支持的最大线程数,超过该数量则排队等待。
keepAliveTime:超过corePoolSize的空闲线程的存活时间。
unit:keeyAliveTime的单位。
workQueue:任务队列,当提交的任务超过线程池支持的最大线程数,则进入该队列排队等待。该队列的选择会对线程池的性能有重大影响。
threadFactory:线程工厂,用于创建线程,一般使用默认,也可自定义。
handler:当提交任务数量超过线程池容量,并且超过排队队列容量后的拒绝策略。

八.线程池五种状态
1.Running,能接受任务以及处理已添加的任务
2.Shutdown,不接受新任务,可以处理已经添加的任务
3.Stop,不接受新任务,不处理已经添加的任务,且中断正在处理的任务
4.Tidying,所有的任务已经终止,ctl记录的“任务数量”未0,ctl负责记录线程池的运行状态与活动线程数量
5.Terminated,线程池彻底终止,线程池彻底转变为terminate状态

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值