关于java:Java-线程池原理总结

9次阅读

共计 3025 个字符,预计需要花费 8 分钟才能阅读完成。

本文首发自「慕课网」,想理解更多 IT 干货内容,程序员圈内热闻,欢送关注 ” 慕课网 ”!

作者:大能 | 慕课网讲师


Java 线程池原理总结

(一)什么是线程池

线程池做的工作次要是管制运行的线程的数量,解决过程中将工作放入队列,而后在线程创立后启动这些工作,如果线程数量超过了最大数量超出数量的线程排队等待,等其它线程执行结束,再从队列中取出工作来执行。

他的次要特点为:

  • 升高资源耗费。通过反复利用已创立的线程升高线程创立和销毁造成的耗费。
  • 进步响应速度。当工作达到时,工作能够不须要的等到线程创立就能立刻执行。
  • 进步线程的可管理性。线程是稀缺资源,如果无限度的创立,不仅会耗费系统资源,还会升高零碎 的稳定性,应用线程池能够进行对立的调配,调优和监控。

(二)线程池的基本原理
线程池的组成个别的线程池次要分为以下 4 个组成部分:

  1. 线程池管理器:用于创立并治理线程池
  2. 工作线程:线程池中的线程
  3. 工作接口:每个工作必须实现的接口,用于工作线程调度其运行
  4. 工作队列:用于寄存待处理的工作,提供一种缓冲机制

ThreadPoolExecutor 的构造方法如下:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) { }

结构函数参数阐明:

线程池都有哪几种工作队列
1、ArrayBlockingQueue:是一个基于数组构造的有界阻塞队列,此队列按 FIFO(先进先出)准则对元素进行排序。
2、LinkedBlockingQueue:一个基于链表构造的阻塞队列,此队列按 FIFO(先进先出)排序元素,吞吐量通常要高于 ArrayBlockingQueue。动态工厂办法 Executors.newFixedThreadPool() 应用了这个队列
3、SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作始终处于阻塞状态,吞吐量通常要高于 LinkedBlockingQueue,动态工厂办法 Executors.newCachedThreadPool 应用了这个队列。
4、PriorityBlockingQueue:一个具备优先级的有限阻塞队列。

回绝策略 :
线程池中的线程曾经用完了,无奈持续为新工作服务,同时,期待队列也曾经排满了,再也塞不下新工作了。这时候咱们就须要回绝策略机制正当的解决这个问题。

JDK 内置的回绝策略如下:

以上内置回绝策略均实现了 RejectedExecutionHandler 接口,若以上策略仍无奈满足理论须要,齐全能够本人扩大 RejectedExecutionHandler 接口。

Java 线程池工作过程

1. 线程池刚创立时,外面没有一个线程。工作队列是作为参数传进来的。不过,就算队列外面有工作,线程池也不会马上执行它们。

2. 当调用 execute() 办法增加一个工作时,线程池会做如下判断:
a) 如果正在运行的线程数量小于 corePoolSize,那么马上创立线程运行这个工作;
b) 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个工作放入队列;
c) 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创立非核心线程立即运行这个工作;
d) 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异样 RejectExecutionException。

3. 当一个线程实现工作时,它会从队列中取下一个工作来执行。

4. 当一个线程无事可做,超过肯定的工夫(keepAliveTime)时,线程池会判断,如果以后运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有工作实现后,它最终会膨胀到 corePoolSize 的大小。

(三)Executor 框架
Executor 框架同 java.util.concurrent.Executor 接口在 Java 5 中被引入 Executor 框架是一个依据一组执行策略调用,调度,执行和管制的异步工作的框架。

无限度的创立线程会引起应用程序内存溢出。所以创立一个线程池是个更好的的解决方案,因为能够限度线程的数量并且能够回收再利用这些线程。利用 Executor 框架能够十分不便的创立一个线程池。

Executors 类是什么?

Executors 能够用于不便的创立线程池。

Java 中的线程池是通过 Executor 框架实现的,该框架中用到了 Executor,Executors,
ExecutorService,ThreadPoolExecutor,Callable 和 Future、FutureTask 这几个类。

常见线程池的快捷创立形式

要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很分明的状况下,很有可能配置的线程池不是较优的,因而在 Executors 类外面提供了一些动态工厂,生成一些罕用的线程池。

newSingleThreadExecutor

创立一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有工作。如果这个惟一的线程因为异样完结,那么会有一个新的线程来代替它。此线程池保障所有工作的执行程序依照工作的提交程序执行。

newFixedThreadPool

创立固定大小的线程池。每次提交一个工作就创立一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会放弃不变,如果某个线程因为执行异样而完结,那么线程池会补充一个新线程。

newCachedThreadPool

创立一个可缓存的线程池。如果线程池的大小超过了解决工作所须要的线程,
那么就会回收局部闲暇(60 秒不执行工作)的线程,当工作数减少时,此线程池又能够智能的增加新线程来解决工作。此线程池不会对线程池大小做限度,线程池大小齐全依赖于操作系统(或者说 JVM)可能创立的最大线程大小。

newScheduledThreadPool

创立一个大小有限的线程池。此线程池反对定时以及周期性执行工作的需要。

(四)为什么不倡议应用 Executors 动态工厂构建线程池

阿里巴巴 Java 开发手册,明确指出不容许应用 Executors 动态工厂构建线程池
起因如下:
线程池不容许应用 Executors 去创立,而是通过 ThreadPoolExecutor 的形式,这样的解决形式让写的同学更加明确线程池的运行规定,躲避资源耗尽的危险

阐明:Executors 返回的线程池对象的弊病如下:
1:FixedThreadPool 和 SingleThreadPool:
容许的申请队列(底层实现是 LinkedBlockingQueue)长度为 Integer.MAX_VALUE,可能会沉积大量的申请,从而导致 OOM
2:CachedThreadPool 和 ScheduledThreadPool
容许的创立线程数量为 Integer.MAX_VALUE,可能会创立大量的线程,从而导致 OOM


欢送关注「慕课网」官网帐号,咱们会始终保持提供 IT 圈优质内容,分享干货常识,大家一起独特成长吧!

本文原创公布于慕课网,转载请注明出处,谢谢合作

正文完
 0