美文网首页工作生活
线程池,使用ThreadPoolExecutor代替Execut

线程池,使用ThreadPoolExecutor代替Execut

作者: 撸完代码送快递 | 来源:发表于2019-07-04 18:17 被阅读0次
image.png

合理使用线程池的好处:

  • 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  • 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
  • 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。但是要做到合理的利用线程池,必须对其原理了如指掌

Executor架构

image.png

在HotSpot虚拟机中,Java中的线程将会被一一映射为操作系统的线程 在Java虚拟机层面,用户将多个任务提交给Executor框架,Executor负责分配线程执行它们; 在操作系统层面,操作系统再将这些线程分配给处理器执行


image.png

Executor框架中的所有类可以分成三类:
1.任务 任务有两种类型:Runnable和Callable。
2.任务执行器 Executor框架最核心的接口是Executor,它表示任务的执行器。
Executor的子接口为ExecutorService。
ExecutorService有两大实现类:ThreadPoolExecutor和ScheduledThreadPoolExecutor。
3.执行结果
Future接口表示异步的执行结果,它的实现类为FutureTask。

ThreadPoolExecutor类

image.png

Executor接口

Executor接口只有一个execute方法,用来替代通常创建或启动线程的方法。

ExecutorService接口

ExecutorService接口继承自Executor接口,提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。增加了shutDown(),shutDownNow(),invokeAll(),invokeAny()和submit()等方法。如果需要支持即时关闭,也就是shutDownNow()方法,则任务需要正确处理中断。

AbstractExecutorService抽象类

提供ExecutorService接口的默认实现方法。

创建线程池的方法

ExecutorService threadPool = new ThreadPoolExecutor(1, 5, 30, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<Runnable>(1024), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

其中线程工厂可以使用guava包中的方法创建:

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();

参数说明:

  • corePoolSize
    核心线程数,默认情况下核心线程会一直存活,即使处于闲置状态也不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut设置为true。
  • maximumPoolSize
    线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时,这个值无效。
  • keepAliveTime
    非核心线程的闲置超时时间,超过这个时间就会被回收。
  • workQueue
    线程池中的任务队列。常用的有三种队列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。
  • threadFactory
    线程工厂,提供创建新线程的功能。
  • RejectedExecutionHandler
    当线程池中的资源已经全部使用,添加新线程被拒绝时,会调用RejectedExecutionHandler的rejectedExecution方法。

线程池规则:
1.如果线程数量<=核心线程数量,那么直接启动一个核心线程来执行任务,不会放入队列中。
2.如果线程数量>核心线程数,但<=最大线程数,并且任务队列是LinkedBlockingDeque的时候,超过核心线程数量的任务会放在任务队列中排队。
3.如果线程数量>核心线程数,但<=最大线程数,并且任务队列是SynchronousQueue的时候,线程池会创建新线程执行任务,这些任务也不会被放在任务队列中。这些线程属于非核心线程,在任务完成后,闲置时间达到了超时时间就会被清除。
4.如果线程数量>核心线程数,并且>最大线程数,当任务队列是LinkedBlockingDeque,会将超过核心线程的任务放在任务队列中排队。也就是当任务队列是LinkedBlockingDeque并且没有大小限制时,线程池的最大线程数设置是无效的,他的线程数最多不会超过核心线程数。
5.如果线程数量>核心线程数,并且>最大线程数,当任务队列是SynchronousQueue的时候,会因为线程池拒绝添加任务而抛出异常。


image.png

使coreThread失效

之前设置的keepAliveTime参数只能使超过此阈值的非核心线程失效,使用allowCoreThreadTimeOut(boolean value)方法将allowCoreThreadTimeOut设置为true则可以将该策略应用于核心线程。

http://www.ideabuffer.cn/2017/04/04/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%EF%BC%9AThreadPoolExecutor/
https://blog.csdn.net/z_s_z2016/article/details/81674893

相关文章

网友评论

    本文标题:线程池,使用ThreadPoolExecutor代替Execut

    本文链接:https://www.haomeiwen.com/subject/ggxrhctx.html