java多线程

多线程之线程池

2019-11-10  本文已影响0人  初夏时的猫

今天学习了线程池。java有各种池,对于初学者而言听着都头疼。
下面我们来了解一下什么是线程池。
一:线程池的概述
试想,并发的线程数量很多,频繁的创建线程和销毁线程需要时间,而如果每个线程执行任务的时间又很短,那我们就可以用线程池来提高性能。它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。线程池技术关注如何缩短/调整创建销毁线程的时间。

一个线程池包括以下四个基本组成部分:
1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
java中的线程池
没学过线程池的时候,觉得一定很难。然而在java中,线程池就是juc中的接口和类,想学会简单的使用其实并不难。
(1)构造方法

图片.png
corePoolSize:核心池的大小,这个参数跟后面讲述的线程池的实现原理有非常大的关系。
maximumPoolSize:线程池最大线程数,这个参数也是一个非常重要的参数,它表示在线程池中最多能创建多少个线程。
keepAliveTime:表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0。
unit:参数keepAliveTime的时间单位。
workQueue:一个阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响。
(2)常用方法
图片.png
1.Executor接口中只有一个execute方法,在ThreadPoolExecutor中得到实现。
2.ExecutorService定义了shutdown,shutdownNow,submit等方法。
3.AbstractExecutorService实现了submit方法。
还有一些其他方法,笔者水平有限只看了几个主要的,剩下的有兴趣的同学可以自己钻研。
shutdown:关闭线程池
shutdownNow:即使有线程在运行也立刻关闭线程池。
execute:执行线程。
submit:执行线程并可以返回数据。
(3)拒绝策略(handler)
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
(5)生产工厂中的线程池
(1)newSingleThreadExecutor
单个线程的线程池,即线程池中每次只有一个线程工作,单线程串行执行任务
(2)newFixedThreadExecutor(n)
固定数量的线程池,没提交一个任务就是一个线程,直到达到线程池的最大数量,然后后面进入等待队列直到前面的任务完成才继续执行(3)newCacheThreadExecutor(推荐使用)
可缓存线程池,当线程池大小超过了处理任务所需的线程,那么就会回收部分空闲(一般是60秒无执行)的线程,当有任务来时,又智能的添加新线程来执行。
(4)newScheduleThreadExecutor
大小无限制的线程池,支持定时和周期性的执行线程
三:线程池原理
核心线程(corePool):线程池最终执行任务的角色肯定还是线程,同时我们也会限制线程的数量,所以我们可以这样理解核心线程,有新任务提交时,首先检查核心线程数,如果核心线程都在工作,而且数量也已经达到最大核心线程数,则不会继续新建核心线程,而会将任务放入等待队列。

等待队列 (workQueue):等待队列用于存储当核心线程都在忙时,继续新增的任务,核心线程在执行完当前任务后,也会去等待队列拉取任务继续执行,这个队列一般是一个线程安全的阻塞队列,它的容量也可以由开发者根据业务来定制。

非核心线程:当等待队列满了,如果当前线程数没有超过最大线程数,则会新建线程执行任务,那么核心线程和非核心线程到底有什么区别呢?说出来你可能不信,本质上它们没有什么区别,创建出来的线程也根本没有标识去区分它们是核心还是非核心的,线程池只会去判断已有的线程数(包括核心和非核心)去跟核心线程数和最大线程数比较,来决定下一步的策略。

线程活动保持时间 (keepAliveTime):线程空闲下来之后,保持存货的持续时间,超过这个时间还没有任务执行,该工作线程结束。

饱和策略 (RejectedExecutionHandler):当等待队列已满,线程数也达到最大线程数时,线程池会根据饱和策略来执行后续操作,默认的策略是抛弃要加入的任务。


图片.png
图片.png
上一篇下一篇

猜你喜欢

热点阅读