线程池最核心的一个类:ThreadPoolExecutor.

看一下该类的构造器:

  public ThreadPoolExecutor(int paramInt1, int paramInt2, long paramLong, TimeUnit paramTimeUnit,
            BlockingQueue<Runnable> paramBlockingQueue) {
        this(paramInt1, paramInt2, paramLong, paramTimeUnit, paramBlockingQueue, Executors.defaultThreadFactory(),
                defaultHandler);UI就很难看了;
    }

    public ThreadPoolExecutor(int paramInt1, int paramInt2, long paramLong, TimeUnit paramTimeUnit,
            BlockingQueue<Runnable> paramBlockingQueue, ThreadFactory paramThreadFactory) {
        this(paramInt1, paramInt2, paramLong, paramTimeUnit, paramBlockingQueue, paramThreadFactory, defaultHandler);
    }

    public ThreadPoolExecutor(int paramInt1, int paramInt2, long paramLong, TimeUnit paramTimeUnit,
            BlockingQueue<Runnable> paramBlockingQueue, RejectedExecutionHandler paramRejectedExecutionHandler) {
        this(paramInt1, paramInt2, paramLong, paramTimeUnit, paramBlockingQueue, Executors.defaultThreadFactory(),
                paramRejectedExecutionHandler);
    }

    public ThreadPoolExecutor(int paramInt1, int paramInt2, long paramLong, TimeUnit paramTimeUnit,
            BlockingQueue<Runnable> paramBlockingQueue, ThreadFactory paramThreadFactory,
            RejectedExecutionHandler paramRejectedExecutionHandler) {
        this.ctl = new AtomicInteger(ctlOf(-536870912, 0));
        this.mainLock = new ReentrantLock();
        this.workers = new HashSet();
        this.termination = this.mainLock.newCondition();
        if ((paramInt1 < 0) || (paramInt2 <= 0) || (paramInt2 < paramInt1) || (paramLong < 0L))
            throw new IllegalArgumentException();
        if ((paramBlockingQueue == null) || (paramThreadFactory == null) || (paramRejectedExecutionHandler == null))
            throw new NullPointerException();
        this.corePoolSize = paramInt1;
        this.maximumPoolSize = paramInt2;
        this.workQueue = paramBlockingQueue;
        this.keepAliveTime = paramTimeUnit.toNanos(paramLong);
        this.threadFactory = paramThreadFactory;
        this.handler = paramRejectedExecutionHandler;
    }

corePoolSize :线程池的核心池大小,在创建线程池之后,线程池默认没有任何线程。

当有任务过来的时候才回去创建创建线程执行任务。换个说法,线程池创建之后,线程池中的线程数为0,当任务过来就会创建一个线程去执行,直到线程数达到corePoolSize 之后,就会被到达的任务放在队列中。(注意是到达的任务)。换句更精炼的话:corePoolSize 表示允许线程池中允许同时运行的最大线程数。

maximumPoolSize :线程池允许的最大线程数,他表示最大能创建多少个线程。maximumPoolSize 肯定是大于corePoolSize 。

keepAliveTime :表示线程没有任务是最多保持多久然后停止。默认情况下,只有线程池中线程数大于corePoolSize 时,keepAliveTime 才会起作用。换句话说,当线程池中的线程数大于corePoolSize ,并且一个线程空闲时间达到了keepAliveTime ,那么就是shutdown。

Unit:keepAliveTime 的参数。

workQueue :一个阻塞队列,用来存储等待执行的任务,在线程池中这个参数很重要。

ArrayBlockingQueue和PriorityBlockingQueue使用较少,一般使用LinkedBlockingDeque和SynchronousQueue,

线程池的排列策略和BlockingQueue有关。

threadFactory :线程工厂,用来创建线程。

handler :表示当拒绝处理任务时的策略。

AbortPolicy:丢弃任务并抛出RejectedExecutionException

CallerRunsPolicy:有调用线程处理该任务

DiscardOldestPolicy:丢弃队列最前面的任务,然后重新执行该任务

DiscardPolicy:丢弃任务,不抛出异常

线程池的任务处理策略:

  • 如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;
  • 如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;
  • 如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;
  • 如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。

任务缓存队列及排队策略

  在前面我们多次提到了任务缓存队列,即workQueue,它用来存放等待执行的任务。

  workQueue的类型为BlockingQueue<Runnable>,通常可以取下面三种类型:

  1)ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;

  2)LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;

  3)synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。

线程池的关闭

  ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:

  • shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
  • shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务

四种线程池的介绍和使用

Java多线程高并发学习笔记(三)——深入理解线程池的更多相关文章

  1. JAVA多线程高并发学习笔记(三)——Callable、Future和FutureTask

    为什么要是用Callable和Future Runnable的局限性 Executor采用Runnable作为基本的表达形式,虽然Runnable的run方法能够写入日志,写入文件,写入数据库等操作, ...

  2. Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition

    锁的概念 从jdk发行1.5版本之后,在原来synchronize的基础上,增加了重入锁ReentrantLock. 本文就不介绍synchronize了,有兴趣的同学可以去了解一下,本文重点介绍Re ...

  3. Java多线程高并发学习笔记(一)——Thread&Runnable

    进程与线程 首先来看百度百科关于进程的介绍: 进程是一个具有独立功能的程序关于某个数据集合的一次运行活动.它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体.它不只是程序的代码,还包括当前的 ...

  4. Java多线程高并发学习笔记——阻塞队列

    在探讨可重入锁之后,接下来学习阻塞队列,这边篇文章也是断断续续的写了很久,因为最近开始学ssm框架,准备做一个自己的小网站,后续可能更新自己写网站的技术分享. 请尊重作者劳动成果,转载请标明原文链接: ...

  5. Java 多线程高并发编程 笔记(一)

    本篇文章主要是总结Java多线程/高并发编程的知识点,由浅入深,仅作自己的学习笔记,部分侵删. 一 . 基础知识点 1. 进程于线程的概念 2.线程创建的两种方式 注:public void run( ...

  6. JAVA 多线程和并发学习笔记(三)

    Java并发编程中使用Executors类创建和管理线程的用法 1.类 Executors Executors类可以看做一个“工具类”.援引JDK1.6 API中的介绍: 此包中所定义的 Execut ...

  7. JAVA 多线程和并发学习笔记(四)

    1. 多进程 实现并发最直接的方式是在操作系统级别使用进程,进程是运行在它自己的地址空间内的自包容的程序.多任务操作系统可以通过周期性地将CPU从一个进程切换到另一个进程,来实现同时运行多个进程. 尽 ...

  8. JAVA 多线程和并发学习笔记(二)

    一.Java中创建线程方法 1. 继承Thread类创建线程类 定义Thread类的子类,重写该类的run()方法.该方法为线程执行体. 创建Thread子类的实例.即线程对象. 调用线程对象的sta ...

  9. JAVA 多线程和并发学习笔记(一)

    一.进程与线程 1. 进程 当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中的程序.进程是操作系统进行资源分配和调度的一个独立单位.进程的三个特征: 独立性 独立存在的实体,每个进程都有 ...

随机推荐

  1. JavaWeb(一)JSP基础组成

    JSP(Java sever pages):一种用于开发动态web页面(资源)的技术. jsp页面是在服务器上运行的一个页面,一个jsp页面就是一个类.写jsp就像在写html,jsp允许在页面中编写 ...

  2. Orleans简单配置

    Orleans简单配置 这是Orleans系列文章中的一篇.首篇文章在此 话说曾几何时,我第一次看到xml文件,心中闪过一念想:"这<>是什么鬼?"-用ini或者jso ...

  3. Linux下自动备份MySQL数据库并上传到远程FTP服务器

    Linux下自动备份MySQL数据库并上传到远程FTP服务器且删除指定日期前的备份Shell脚本 说明:  1.备份MySQL数据库存放目录/var/lib/mysql下面的xshelldata数据库 ...

  4. 【Maven】项目中没有resources目录

    在eclipse中创建maven项目,src/main/只有java没有resources目录 解决办法: 1.项目右键properties 2.Java Build Path 中移除JRE Syst ...

  5. Ubuntu 环境 samba的安装&配置

    一.samba的安装: sudo apt-get install samba sudo apt-get install smbfs sudo apt-get install cifs-utils (新 ...

  6. 关于react-redux中的connect函数

    示例代码 'use strict'; import React from 'react'; import { connect } from 'react-redux'; class demo exte ...

  7. 谈一谈EasyUI中TreeGrid的过滤功能

    写在最前面 这个星期一直在纠结easyui的treegrid的过滤功能,原因呢,自然是项目中一个莫名奇妙的需求. easyui虽说是后端程序员的前端框架,但是说句实话,除去api,让我直接写里面的节点 ...

  8. Maven 中央仓库及阿里云仓库地址

    Maven 中央仓库地址: 1. http://www.sonatype.org/nexus/ 2. http://mvnrepository.com/ 3. http://repo1.maven.o ...

  9. 【Java IO流】字节流和字符流详解

    字节流和字符流 对于文件必然有读和写的操作,读和写就对应了输入和输出流,流又分成字节和字符流. 1.从对文件的操作来讲,有读和写的操作——也就是输入和输出. 2.从流的流向来讲,有输入和输出之分. 3 ...

  10. JS跨域请求 JSONP B/S全代码

    Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨域请求,一律不准:Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有 ...