Java线程池

我觉得要比较容易理解Java线程池,要逐步搞懂这么几个问题。

1、Java线程池是一个放线程的池子,指的就是里面有很多个线程,池子怎么实现呢,用什么东西来表示,有考虑到数据结构吗,跟连接池类似吗。
2、里面的线程是用来干什么的。
3、线程池中的线程是在什么时候创建的,有哪些方式可以创建呢。
4、池中线程个数怎么设置,若是超过了怎么办,若是还没达到怎么办。
5、线程是用来执行任务的,但是这个任务要怎么定义呢
6、线程和任务怎么绑定。
7、线程池中的线程顺序是怎样的,是先来就先执行吗。
8、线程和任务的个数有怎样的关系。
9、任务在等待执行的过程放在哪里,在等待期间可以做些什么呢。
10、线程池有没有生命周期,难道是永远都活着的吗。

(1)Java中的线程池用ThreadPoolExecutor类来表示,这个类继承自抽象类AbstractExecutorService,AbstractExecutorService又实现了ExecutorService接口,ExecutorService接口又继承了Executor接口。
(2)通过线程池来创建线程,得向池中指定一些参数吧,例如创建多少个线程,最多只能创建多少,不然无限制地创建下去,肯定是不行的,因此在创建线程池的时候就可以把这些东西指定了,创建线程池的构造方式有四种:
这里写图片描述
从参数便可以看到几个构造方式的不同,但是若跟源码之后,会发现,前面三个都调用了第四个。

在这里是通过new的方式来创建线程池,但是还有一种方式可以获得线程池,那就是通过Executors的静态方法方式可以获得线程池。
这里写图片描述
跟源码之后会发现,其实这些静态方法里面也是调用了ThreadPoolExecutor的构造方法,例如:
这里写图片描述

这两种方式其实都差不多,只不过第二种帮我们配置了一些参数。
(3)获得了线程池的实例,是不是可以得到这个线程池里面的一些东西,例如哪些线程正在执行,哪些已经执行完了,还在等待的有哪些,当然更重要的是,我们要知道,里面那么多线程是怎么组织起来的,程序员给方法或变量起名字是有规范的,不然别人很难读懂这个变量大概是什么意思的,这个方法是干什么的。
这里写图片描述
这个方法是顶层Executor接口的,最终在ThreadPoolExecutor里面有了具体的实现,这个方法就是用来让线程池执行某个任务的。

(4)线程池也是有生命周期的(旧版本不是用volatile修饰的变量来表示的)。
这里写图片描述
runState表示当前线程池的状态。
当线程池初始创建的时候,是running态。
当线程池处于shutdown态的时候,此线程池不能够接受新的任务,它会等待所有的任务执行完毕。
当线程池处于stop状态的时候,此线程不能接受新的任务,并且会去尝试终止正在执行的任务。
那线程池什么时候处于什么状态呢。当调用了shutdown()方法的时候就会处于shutdown状态,当调用了shutdownNow()方法的时候就会处于stop状态。
(5)线程池中的线程是有数量限制的,根据任务类型来设置线程数量,如果是CPU密集型,则数量为NCPU+1,如果是IO密集型,则数量为2*NCPU,很多时候,为了安全性,还是会设置上限,当新的任务来的时候,如果正常数量的线程都在用着,那么就用一个队列数据结构把新的任务缓存起来,若是新任务增长速度大于线程完成任务的速度,这时可以在线程数量还没有达到上限的时候创建新的线程来执行任务,但若是达到了上限而且任务缓存队列已经满了的话,则有必要采取拒绝措施,拒绝后续任务的到来。
这里有两个概念:
任务缓存队列
这里写图片描述
这里写图片描述
通常有这四种情况,我们选用一个东西的时候肯定是根据它的某些特征。
A、ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小。
B、PriorityBlockingQueue:基于优先级的队列。
C、LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定大小,则默认为Integer.MAX_VALUE。
D、synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新的任务。

任务的拒绝措施:如果线程池中任务缓存队列已经满了并且线程池中线程数目达到maxmunPoolSize,如果还有任务来,就会采取任务拒绝策略,通常有一些四种策略。
A、ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
B、ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
C、ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
D、ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

GitChat分享:如何成为程序员面霸
http://gitbook.cn/gitchat/activity/59e9a74ea8275c3bd0b61487

知乎Live:Java程序员的成长体系
https://www.zhihu.com/lives/904735941707587584

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值