博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java中的线程池
阅读量:5035 次
发布时间:2019-06-12

本文共 2894 字,大约阅读时间需要 9 分钟。

Java中的线程池

 

一、线程池的好处

  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

  2. 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。

  3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

 

二、线程池的种类

  Java通过Executors提供四种线程池

  1. newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

  2. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  3. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

  4. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

 

三、 ThreadPoolExecutor

  1. 上述四种Java中的线程池都是用ThreadPoolExecutor实现的

  2. ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)

  3. ThreadPoolExecutor继承了AbstractExecutorService抽象类,AbstractExecutorService实现了ExecutorService接口,ExecutorService继承了Executor 接口

    • corepoolsize:核心池的大小,默认情况下,在创建了线程池之后,线程池中线程数为 0,当有任务来之后,就会创建一个线程去执行任务,当线程池中线程数达到 corepoolsize 后,就把任务放在任务缓存队列中。
    • Maximumpoolsize:线程池中最多创建多少个线程。
    • Keeplivetime:线程没有任务执行时,最多保存多久的时间会终止,默认情况下,当线程池中线程数>corepoolsize ,Keeplivetime 才起作用,直到线程数不大于 corepoolsize。
    • workQueue:阻塞队列,用来存放等待被执行的任务
    • threadFactory:线程工厂,用来创建线程。

     4. ThreadPoolExecutor继承了AbstractExecutorService抽象类,AbstractExecutorService实现了ExecutorService接口,ExecutorService继承了Executor 接口

  

 

四、 线程池生命周期/状态转换过程

  1. RUNNING :当线程池创建后,初识为Running状态,能接受新提交的任务,并且也能处理阻塞队列中的任务;

  2. SHUTDOWN:关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务。在线程池处于 RUNNING 状态时,调用 shutdown()方法会使线程池进入到该状态。(finalize() 方法在执行过程中也会调用shutdown()方法进入该状态);

  3. STOP:不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。在线程池处于 RUNNING 或 SHUTDOWN 状态时,调用 shutdownNow() 方法会使线程池进入到该状态;

  4. TIDYING:如果所有的任务都已终止了,workerCount (有效线程数) 为0,线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态。

 

五、 线程池的组成

  1. 线程池管理器:用于创建并管理线程池

  2. 工作线程:线程池中的线程

  3. 任务接口:每个任务必须实现的接口,用于工作线程调度其运行

  4. 任务队列:用于存放待处理的任务,提供一种缓冲机制

 

六、 execute方法执行流程

  1. addWorker方法的主要工作是在线程池中创建一个新的线程并执行,firstTask参数用于指定新增的线程执行的第一个任务,core参数为true表示在新增线程时会判断当前活动线程数是否少于corePoolSize,false表示新增线程前需要判断当前活动线程数是否少于maximumPoolSize

  2. 下述添加到工作线程并执行,调用的就是addWorker()

  3. submit方法能获得线程执行后的返回值,底层还是调用了execute方法

  4. execute方法工作流程

    • 若当前线程池中线程数<corepoolsize,则每来一个任务就创建一个线程去执行,即使现在的线程是空闲的。
    • 若当前线程池中线程数>=corepoolsize,会尝试将任务添加到任务缓存队列中去,若添加成功,则任务会等待空闲线程将其取出执行,若添加失败,则尝试创建线程去执行这个任务。
    • 若当前线程池中线程数>= Maximumpoolsize,则采取拒绝策略有 4 种,

      1)abortpolicy 丢弃任务,抛出 RejectedExecutionException

      2)discardpolicy 拒绝执行,不抛异常

      3)discardoldestpolicy 丢弃任务缓存队列中最老的任务,并且尝试重新提交新的任务

      4)callerrunspolicy 有反馈机制,使任务提交的速度变慢。

 

七、 工作线程整个工作流程

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

  2. 当调用 execute()/submit() 方法添加一个任务时,会进行上述线程数量判断过程(线程池创建线程时,会将线程封装成工作线程Worker),并执行addWorker() 添加并执行任务

  3. 调用addWorker()中的runWorker()方法执行任务firstTask,firstTask执行完成之后,通过getTask方法从阻塞队列中获取等待的任务,如果队列中没有任务,getTask方法会被阻塞并挂起,不会占用cpu资源;

  4. 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。

 

转载于:https://www.cnblogs.com/Demrystv/p/9404582.html

你可能感兴趣的文章
.NET Framework 卸载工具 -- .NET Framework Cleanup Tool User's Guide
查看>>
如何为ios程序增加itunes同步功能
查看>>
Hibernate QBC 简单收集
查看>>
cf B. Hungry Sequence
查看>>
C语言数组删除增加一个元素
查看>>
Spring MVC JSON 实现JsonSerializer Date类型转换
查看>>
Citrix 服务器虚拟化之十 Xenserver高可用性HA
查看>>
三层架构与MVC
查看>>
js原生appendChild的bug
查看>>
在word 中复选框划勾或叉的方法
查看>>
工厂模式
查看>>
比例运算和求和电路
查看>>
Luogu P3927 SAC E#1 - 一道中档题 Factorial
查看>>
scrapy框架初识
查看>>
卡片游戏
查看>>
bat 获取当前目录的父目录
查看>>
RocksDB系列二十二:RocksDB使用场景和特性
查看>>
WordPress插件开发教程:(一)插件简介
查看>>
Android学习笔记之View(一):LayoutInflater
查看>>
.net core 发布到docker
查看>>