引言

Android的线程池概念来自于Java的Executor,真正的线程池实现为ThreadPoolExecutor。在Android中,提供了4类不同的线程池,具体下面会说到。为什么使用线程池呢?而不是使用Thread创建线程呢?因为使用线程池有以下几个优点:

  • 重用线程池的线程,避免因为线程的创建和销毁所带来的性能开销
  • 能有效控制线程池的最大并发数,避免线程之间抢占资源导致阻塞
  • 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能

所以需要多次创建Thread时使用线程池较好。

ThreadPoolExecutor

它是线程池的真正实现,构造函数提供一系列的参数配置线程池。

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
  • corePoolSize:核心线程数,默认情况下,即时处于闲置状态下,核心线程会在线程一直存活;如果设置allowCoreThreadTimeOut为true,闲置的核心线程等待任务期间会有超时策略,时间间隔由keepAliveTime设置,最大为CPU核心数+1
  • maximumPoolSize:线程池容纳最大线程数,当活动线程数超过这个数值,后续的新任务会导致阻塞,最大为CPU核心数2倍+1
  • keepAliveTime:非核心线程闲置时超时的时长,如果设置allowCoreThreadTimeOut为true,即作用于闲置的核心线程
  • unit:时间单位,使用TimeUnit枚举
  • workQueue:线程池中的任务队列,通过线程池execute方法提交Runnable对象会存储这个参数中,容量为128
  • threadFactory:线程工厂,为线程池提供创建新线程的功能
  • handler:线程池对拒绝任务的处理策略。一般是队列已满或者无法成功执行任务,这时ThreadPoolExecutor会调用handler的rejectedExecution方法来通知调用者,有四个策略:
    • ThreadPoolExecutor.AbortPolicy() 直接抛出异常RejectedExecutionException
    • ThreadPoolExecutor.CallerRunsPolicy() 直接调用run方法并且阻塞执行
    • ThreadPoolExecutor.DiscardPolicy() 直接丢弃后来的任务
    • ThreadPoolExecutor.DiscardOldestPolicy() 丢弃在队列中队首的任务

执行任务规则可用currentSize表示线程池中当前线程数量,将上述过程可以表示如下

  • 当currentSize < corePoolSize时,直接启动一个核心线程并执行任务
  • 当currentSize>=corePoolSize、并且workQueue未满时,添加进来的任务会被安排到workQueue中等待执行
  • 当workQueue已满,但是currentSize<maximumPoolSize时,会立即开启一个非核心线程来执行任务
  • 当currentSize>=corePoolSize、workQueue已满、并且currentSize>maximumPoolSize时,调用handler默认抛出RejectExecutionExpection异常
  • 当currentSize >corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
  • 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

FixedThreadPool

通过Executors的newFixedThreadPool方法创建,它是一种线程数量固定的线程池,当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭了。当所有的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来。由于FixedThreadPool只有核心线程并且这些核心线程不会被回收,这意味着它能够更加快速地响应外界的请求。

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

CachedThreadPool

通过Executors的newCachedThreadPool方法创建,它是一种线程数量不定的线程池,它只有非核心线程,并且最大线程数为Integer.MAX_VALUE,从CachedThreadPool的特性来看,这类线程池比较适合执行大量的耗时较少的任务,当整个线程池都处于闲置状态时,线程池中的线程都会超时而被停止,这个时候CachedThreadPool之中实际上是没有任何线程的,它几乎是不占用任何系统资源的。

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

ScheduledThreadPool

通过Executors的newScheduledThreadPool方法创建,它的核心线程是固定的,非核心线程数是没有限制的,主要用于执行定时任务和具有固定周期的重复任务。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}

SingleThreadExecutor

通过Executors的newSingleThreadExecutor方法创建,它只有一个核心线程,确保所有任务都在同一个线程中按顺序执行,使得这些不需要处理线程同步问题。

public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}

Android ThreadPoolExecutor线程池的更多相关文章

  1. 13.ThreadPoolExecutor线程池之submit方法

    jdk1.7.0_79  在上一篇<ThreadPoolExecutor线程池原理及其execute方法>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法 ...

  2. ThreadPoolExecutor 线程池的源码解析

    1.背景介绍 上一篇从整体上介绍了Executor接口,从上一篇我们知道了Executor框架的最顶层实现是ThreadPoolExecutor类,Executors工厂类中提供的newSchedul ...

  3. j.u.c系列(01) ---初探ThreadPoolExecutor线程池

    写在前面 之前探索tomcat7启动的过程中,使用了线程池(ThreadPoolExecutor)的技术 public void createExecutor() { internalExecutor ...

  4. Java并发——ThreadPoolExecutor线程池解析及Executor创建线程常见四种方式

    前言: 在刚学Java并发的时候基本上第一个demo都会写new Thread来创建线程.但是随着学的深入之后发现基本上都是使用线程池来直接获取线程.那么为什么会有这样的情况发生呢? new Thre ...

  5. ThreadPoolExecutor 线程池

    TestThreadPoolExecutorMain package core.test.threadpool; import java.util.concurrent.ArrayBlockingQu ...

  6. 十、自定义ThreadPoolExecutor线程池

    自定义ThreadPoolExecutor线程池 自定义线程池需要遵循的规则 [1]线程池大小的设置 1.计算密集型: 顾名思义就是应用需要非常多的CPU计算资源,在多核CPU时代,我们要让每一个CP ...

  7. Executors、ThreadPoolExecutor线程池讲解

    官方+白话讲解Executors.ThreadPoolExecutor线程池使用 Executors:JDK给提供的线程工具类,静态方法构建线程池服务ExecutorService,也就是Thread ...

  8. SpringBoot项目框架下ThreadPoolExecutor线程池+Queue缓冲队列实现高并发中进行下单业务

    主要是自己在项目中(中小型项目) 有支付下单业务(只是办理VIP,没有涉及到商品库存),目前用户量还没有上来,目前没有出现问题,但是想到如果用户量变大,下单并发量变大,可能会出现一系列的问题,趁着空闲 ...

  9. 手写线程池,对照学习ThreadPoolExecutor线程池实现原理!

    作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...

随机推荐

  1. modbus转乐鑫物联网平台上传工具

    乐鑫平台推荐个人用户使用 界面比较简洁

  2. Oracle通过序列+触发器实现主键自增

    接触oracle没多久,在建表的时候发现还不会如何设置主键自动增长.和mysql的设置为AUTO_INCREMENT属性相比,要复杂很多,所以现在记录起来. 我使用的是序列+触发器的方式. 现在已经创 ...

  3. [Python] networkx入门 转

    networkx是python的一个第三方包,可以方便地调用各种图算法的计算. 通过调用python画图包matplotlib能实现图的可视化. 1.安装 正好整理一下python第三方包的安装方法. ...

  4. Android精通教程V

    前言 大家好,给大家带来Android精通教程V的概述,希望你们喜欢 前言 如果你想学习Android开发,那你就要了解Java编程,这是基础,也是重点,如果没学Java语法就先学习,再来学Andro ...

  5. [视频]K8飞刀 Google黑客功能教程

    [视频]K8飞刀 Google黑客功能教程 链接:https://pan.baidu.com/s/1kbK5jNH8ZaddUEeQ9IwTaw 提取码:lwl6

  6. A Painless Q-learning Tutorial (一个 Q-learning 算法的简明教程)

        本文是对 http://mnemstudio.org/path-finding-q-learning-tutorial.htm 的翻译,共分两部分,第一部分为中文翻译,第二部分为英文原文.翻译 ...

  7. 在Windows环境中安装Neo4j

    图形数据库(Graph Database)是NoSQL数据库家族中特殊的存在,用于存储丰富的关系数据,Neo4j 是目前最流行的图形数据库,支持完整的事务,在属性图中,图是由顶点(Vertex),边( ...

  8. 如何优化Mysql千万级快速分页,limit优化快速分页,MySQL处理千万级数据查询的优化方案

    如何优化Mysql千万级快速分页,limit优化快速分页,MySQL处理千万级数据查询的优化方案

  9. Redis 内存模型

    了解 Redis 的 5 种对象类型(字符串.哈希.列表.集合.有序集合)的用法和特点的基础,了解 Redis 的内存模型,对 Redis 的使用有很大帮助,例如: 估算 Redis 内存使用量.内存 ...

  10. eclipse配置ant开发环境,一键部署项目

    ANT出现之前,编译和部署Java应用需要使用包括特定平台的脚本.Make文件.不同的IDE以及手工操作等组成的大杂烩.现在,几乎所有的开源Java项目都在使用Ant,许多公司的开发项目也在使用Ant ...