1.线程池介绍

    线程池是一种线程使用模式。线程由于具有空闲(eg:等待返回值)和繁忙这种不同状态,当数量过多时其创建、销毁、调度等都会带来开销。线程池维护了多个线程,当分配可并发执行的任务时,它负责调度线程执行工作,执行完毕后线程不关闭而是返回线程池,可以执行后续其他任务。举例来说,外卖餐厅对每个订单分配一个临时工,完成订单立刻辞退,成本和管理开销巨大,而且如果取餐点的空间有限,大量的人挤满在那反而会影响工作效率,因此选择签下固定数量的外卖小哥让他们不断往返于目的地和店家之间配送。

通俗来讲,线程池就是为了减少开销而复用线程,实现了任务内容和线程分离的一种机制。如果机器有100核而且其他资源充足,直接启动100个无冲突的并发线程应该是比使用线程池要快,但是受限于目前的硬件能力,线程池就很有必要了。Java的Executor框架用于执行异步任务,方法 executor(Runnable runnable) 可以接收Runnable对象。Executor有一个子类接口ExecutorService,提供了生命周期管理的方法,以及可跟踪一个或多个异步任务执行状况返回Future的方法。

2.工厂模式创建线程池

Excutors运用工厂模式提供线程池实现方式,返回ExecutorService

  1. newSingleThreadExecutor,单线程的线程池,实际上是串行执行任务,如果该线程出现异常则会有新线程替代它工作,其优势是任务会按照提交顺序执行。

  2. newFixedThreadPool,固定大小线程池,每次新提交任务时如果线程数没达到最大就创建新线程执行任务,否则任务进入等待状态。

  3. newCachedThreadPool,可缓存的线程池,大小依赖于操作系统(JVM)最大值。线程池大于任务数时回收部分空闲(60s)线程,任务数增加时添加新线程。

问题在于,前两者请求处理队列的堆积会消耗内存,第三个创建过多线程也会这样。同时,拒绝策略在Executors中无效。

3.自定义创建

ThreadPoolExecutor是线程池的实现方法签名:

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) //后两个参数为可选参数
  1. corePoolSize,核心线程数,同时处于执行状态的线程最大值(或者说,接单配送中的小哥人数上限)。当线程数少于该值时,新的任务会创建新的线程执行。allowCoreThreadTimeOut属性不设置为true(默认false)时,闲置的核心线程也不会销毁。
  2. maximumPoolSize,线程总数,等于核心线程+非核心线程数,不小于核心线程数。
  3. keepAliveTime,线程进入不活跃状态后到销毁前的时间,通过Unit参数设置单位。通常只适用于非核心线程,allowCoreThreadTimeOut为true时核心线程也适用。
  4. workQueue,任务队列,当核心线程满时新任务进入该队列等待,当队列满时创建非核心线程执行任务。
    • SynchronousQueue:等于没有队列,任何任务都直接给线程处理,为防止线程数量达到最大值,通常设置maximumPoolSize为Integer.MAX_VALUE
    • LinkedBlockingQueue:无限长阻塞队列,总线程数永远等于核心线程数,未执行的任务都在队列里排队
    • ArrayBlockingQueue:定长队列,队列满时新建非核心线程,达到maximumPoolSize后出错
    • DelayQueue,当任务实现Delayed接口时,任务入队等待到指定延时后开始执行
  5. threadFactory,线程工厂
  6. handler,任务被拒绝时的策略
    • AbortPolicy,默认策略,将抛出RejectExecutorException
    • CallerRunsPolicy,线程池未关闭时调用线程(任务提交者)直接执行该任务
    • DiscardPolicy,直接丢弃不抛出异常
    • DiscardOldestPolicy,丢弃队列最前的任务后重试当前任务

4.生命周期

ExecutorService的生命周期包括了运行、关闭和终止三种状态,在初始化创建时处于运行状态。使用submit方法执行Runnable或者Callable对象。shutdown方法等待提交的任务执行完成并不再接受新任务,在完成全部提交的任务后关闭;shutdownNow方法将强制终止所有运行中的任务并不再允许提交新任务。

Java基础学习——多线程之线程池的更多相关文章

  1. java 22 - 20 多线程之线程池

    程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互. 而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池. 线程池里的每一个线程代码结束后 ...

  2. Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

  3. java基础:简单实现线程池

    前段时间自己研究了下线程池的实现原理,通过一些源码对比,发现其实核心的东西不难,于是抽丝剥茧,决定自己实现一个简单线程池,当自已实现了出一个线程池后.发现原来那么高大上的东西也可以这么简单. 先上原理 ...

  4. Java基础学习——多线程之创建任务

    这次来盘点一下Java中用线程执行任务的写法. 1.扩展Thread 最基本的实现方法是在创建一个继承Thread的新类,在其中覆盖run()方法执行任务. public class MyThread ...

  5. 黑马程序员——JAVA基础之多线程的线程间通讯等

    ------- android培训.java培训.期待与您交流! ---------- 线程间通讯: 其实就是多个线程在操作同一个资源,但是动作不同. wait(); 在其他线程调用此对象的notif ...

  6. Java并发包源码学习系列:线程池ScheduledThreadPoolExecutor源码解析

    目录 ScheduledThreadPoolExecutor概述 类图结构 ScheduledExecutorService ScheduledFutureTask FutureTask schedu ...

  7. Java多线程与线程池技术

    一.序言 Java多线程编程线程池被广泛使用,甚至成为了标配. 线程池本质是池化技术的应用,和连接池类似,创建连接与关闭连接属于耗时操作,创建线程与销毁线程也属于重操作,为了提高效率,先提前创建好一批 ...

  8. Java 多线程:线程池

    Java 多线程:线程池 作者:Grey 原文地址: 博客园:Java 多线程:线程池 CSDN:Java 多线程:线程池 工作原理 线程池内部是通过队列结合线程实现的,当我们利用线程池执行任务时: ...

  9. JAVA多线程(三) 线程池和锁的深度化

    github演示代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-servic ...

随机推荐

  1. python基础===一行 Python 代码实现并行(转)

    原文:https://medium.com/building-things-on-the-internet/40e9b2b36148 译文:https://segmentfault.com/a/119 ...

  2. CEC2017 benchmark function调用接口

    CEC2017 benchmark function可以从这里下载. 导师最近给了个课题让我自己研究,跟智能优化算法相关的,必不可免的要用到最新的CEC2017 benchmark function, ...

  3. git内部原理

    Git 内部原理 无论是从之前的章节直接跳到本章,还是读完了其余章节一直到这——你都将在本章见识到 Git 的内部工作原理 和实现方式. 我们发现学习这部分内容对于理解 Git 的用途和强大至关重要. ...

  4. 2016-2017-2 20155309南皓芯java第四周学习总结

    教材内容总结 这次我们学习的还是两章的内容,学习任务量跟上次比的话大体上来讲是差不多的. 继承与多态 继承 继承也符合DRY(Don't Repeat Yourself)原则 Role role1 = ...

  5. stellar

    13) Sundapeng.123 12) 有个问题问下,这里的私钥和公钥是随意生成的吗? 当前的配置启动的时候报错了 11) ssh root@39.108.127.234 Liansen2018 ...

  6. tidb 记录文档

    ansible-playbook stop.yml   / start.yml 重启集群,在ansible目录下执行 SHOW STATS_META; 查看统计信息 重启集群:ansible-play ...

  7. linux删除特殊字符命名的文件

    今天在服务器上不小心创建了一个!命名的文件还有一个\命名的文件,本来想用转义字符进行删除,又担心误删了项目文件....最后找到最好的解决办法 如下: ls -i  查看文件inum值 执行删除inum ...

  8. swftools中的pdf2swf转换Error overflow ID 65535 解决办法

    近几日因为项目需要在线转换pdf到swf实现电子期刊阅读,用到了这个工具,版本是:swftools-0.9.2.tar.gz 当然也遇到了很头疼的问题,那就是在转换pdf中色彩图形比较复杂的页时会抛出 ...

  9. Web前端开发最佳实践(8):还没有给CSS样式排序?其实你可以更专业一些

    前言 CSS样式排序是指按照一定的规则排列CSS样式属性的定义,排序并不会影响CSS样式的功能和性能,只是让代码看起来更加整洁.CSS代码的逻辑性并不强,一般的开发者写CSS样式也很随意,所以如果不借 ...

  10. centos7.x firewall简单使用

    开放一个端口: firewall-cmd --zone=public --add-port=22/tcp –permanent 开放一个范围端口对外部所有地址生效: firewall-cmd --zo ...