完全解析Android多线程中线程池ThreadPool的原理和使用
作者:Carson_Ho 发布时间:2022-04-07 20:19:40
前言对于多线程,大家应该很熟悉。但是,大家了解线程池吗?今天,我将带大家全部学习关于线程池的所有知识。
目录
1. 简介
2. 工作原理
2.1 核心参数线程池中有6个核心参数,具体如下
上述6个参数的配置 决定了 线程池的功能,具体设置时机 = 创建 线程池类对象时 传入
ThreadPoolExecutor类 = 线程池的真正实现类
开发者可根据不同需求 配置核心参数,从而实现自定义线程池
// 创建线程池对象如下// 通过 构造方法 配置核心参数 Executor executor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory );// 构造函数源码分析 public ThreadPoolExecutor (int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable workQueue>, ThreadFactory threadFactory )
注:Java 里已内置4种常用的线程池(即 已经配置好核心参数),下面会详细说明
2.2 内部原理逻辑
当线程池运行时,遵循以下工作逻辑
3. 使用流程
线程池的使用流程如下
// 1. 创建线程池 // 创建时,通过配置线程池的参数,从而实现自己所需的线程池 Executor threadPool = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory ); // 注:在Java中,已内置4种常见线程池,下面会详细说明// 2. 向线程池提交任务:execute() // 说明:传入 Runnable对象 threadPool.execute(new Runnable() { @Override public void run() { ... // 线程执行任务 } });// 3. 关闭线程池shutdown() threadPool.shutdown(); // 关闭线程的原理 // a. 遍历线程池中的所有工作线程 // b. 逐个调用线程的interrupt()中断线程(注:无法响应中断的任务可能永远无法终止) // 也可调用shutdownNow()关闭线程:threadPool.shutdownNow() // 二者区别: // shutdown:设置 线程池的状态 为 SHUTDOWN,然后中断所有没有正在执行任务的线程 // shutdownNow:设置 线程池的状态 为 STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表 // 使用建议:一般调用shutdown()关闭线程池;若任务不一定要执行完,则调用shutdownNow()
4. 常见的4类功能线程池
根据参数的不同配置,Java中最常见的线程池有4类:
定长线程池(FixedThreadPool)定时线程池(ScheduledThreadPool )可缓存线程池(CachedThreadPool)单线程化线程池(SingleThreadExecutor)
即 对于上述4类线程池,Java已根据 应用场景 配置好核心参数
4.1 定长线程池(FixedThreadPool)特点:只有核心线程 & 不会被回收、线程数量固定、任务队列无大小限制(超出的线程任务会在队列中等待)应用场景:控制线程最大并发数具体使用:通过 Executors.newFixedThreadPool() 创建示例:
// 1. 创建定长线程池对象 & 设置线程池线程数量固定为3ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);// 2. 创建好Runnable类线程对象 & 需执行的任务Runnable task =new Runnable(){ public void run(){ System.out.println("执行任务啦"); } };// 3. 向线程池提交任务:execute()fixedThreadPool.execute(task);// 4. 关闭线程池fixedThreadPool.shutdown();
4.2 定时线程池(ScheduledThreadPool )特点:核心线程数量固定、非核心线程数量无限制(闲置时马上回收)应用场景:执行定时 / 周期性 任务使用:通过Executors.newScheduledThreadPool()创建示例:
// 1. 创建 定时线程池对象 & 设置线程池线程数量固定为5ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);// 2. 创建好Runnable类线程对象 & 需执行的任务Runnable task =new Runnable(){ public void run(){ System.out.println("执行任务啦"); } };// 3. 向线程池提交任务:schedule()scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延迟1s后执行任务scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// 延迟10ms后、每隔1000ms执行任务// 4. 关闭线程池scheduledThreadPool.shutdown();
4.3 可缓存线程池(CachedThreadPool)特点:只有非核心线程、线程数量不固定(可无限大)、灵活回收空闲线程(具备超时机制,全部回收时几乎不占系统资源)、新建线程(无线程可用时)
任何线程任务到来都会立刻执行,不需要等待
应用场景:执行大量、耗时少的线程任务 使用:通过Executors.newCachedThreadPool()创建 示例:
// 1. 创建可缓存线程池对象ExecutorService cachedThreadPool = Executors.newCachedThreadPool();// 2. 创建好Runnable类线程对象 & 需执行的任务Runnable task =new Runnable(){ public void run(){ System.out.println("执行任务啦"); } };// 3. 向线程池提交任务:execute()cachedThreadPool.execute(task);// 4. 关闭线程池cachedThreadPool.shutdown();//当执行第二个任务时第一个任务已经完成//那么会复用执行第一个任务的线程,而不用每次新建线程。
4.4 单线程化线程池(SingleThreadExecutor)
特点:只有一个核心线程(保证所有任务按照指定顺序在一个线程中执行,不需要处理线程同步的问题)
应用场景:不适合并发但可能引起IO阻塞性及影响UI线程响应的操作,如数据库操作,文件操作等
使用:通过Executors.newSingleThreadExecutor()创建示例:
// 1. 创建单线程化线程池ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();// 2. 创建好Runnable类线程对象 & 需执行的任务Runnable task =new Runnable(){ public void run(){ System.out.println("执行任务啦"); } };// 3. 向线程池提交任务:execute()singleThreadExecutor.execute(task);// 4. 关闭线程池singleThreadExecutor.shutdown();
4.5 常见线程池 总结 & 对比
5. 总结阅读本文后,相信你已经非常了解线程池 & 用法接下来,我会继续讲解Android开发中关于多线程的知识,具体包括Thread类、Handler、HandlerThread等等,有兴趣可以继续关注Carson_Ho的安卓开发笔记请帮顶 / 评论点赞!因为你的鼓励是我写作的最大动力!
来源:https://blog.csdn.net/carson_ho/article/details/80060201


猜你喜欢
- Java 继承与多态的深入理解1、 什么是继承,继承的特点?子类继承父类的特征和行为,使得子类具有父类的各种属性和方法。或子类从
- MojoUnityJson 是使用C#实现的JSON解析器 ,算法思路来自于游戏引擎Mojoc的C语言实现 Json.h 。借助C#的类库,
- package airthmatic;public class demo10 { public static void main(
- 本文实例讲述了如何计算(或者说,估算)一个Java对象占用的内存数量的方法。分享给大家供大家参考。具体分析如下:通常,我们谈论的堆内存使用的
- ImageCacheconst int _kDefaultSize = 1000;const int _kDefaultSizeBytes
- 在linux主机部署Eureka高可用方案的时候,发现注册到服务中心的服务IP是随机的,由于主机的网卡是多个,随机的IP并不是自己想要的,上
- 什么是https要说https我们得先说SSL(Secure Sockets Layer,安全套接层),这是一种为网络通信提供安全及数据完整
- 本文实例为大家分享了Android点击获取验证码倒计时的具体代码,供大家参考,具体内容如下package com.loaderman.cou
- 本文实例为大家分享了winform可拖动的自定义Label控件,供大家参考,具体内容如下效果预览:实现步骤如下:(1)首先在项目上右击选择:
- 好久没有做web了,JSON目前比较流行,闲得没事,所以动手试试将对象序列化为JSON字符(尽管DotNet Framework
- Mybatis配置返回为修改影响条数mybatis执行update()方法默认返回为匹配的更新记录条数,现在需要将update()方法修改为
- Fragment 的简单用法Fragment 是一种可以嵌入在 Activity 当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的
- 如下所示:Ctrl+1或F2快速修复Ctrl+D快捷删除行Shift+Enter 快速切换到下一行,在本行的任何位置都可Ctrl+F11快速
- SlidingMenu (侧滑菜单形式)在android开发过程中,经常用到,这次我们通过一个简单案例来仿写SlidingMenu 的大体功
- Android之禁止ViewPager滑动实现实例当我们想在同一个Activity或者Fragment中展示多个页面时往往会用到ViewPa
- 本文讲述了使用Qt5.3.0开发Android应用的方法,由于官方资料较少,此处记录开发过程遇到的问题及解决方法。具体步骤如下:1.Andr
- 最近项目需要通过经纬度查询 具体的地址和区域名称,通过查询网络资源,发现提供的大多是得到具体的地址而对区域或城市名称的获取就不是很好把握;在
- 目录一、图示二、链表的概念及结构三、单链表的实现四、完整代码的展示一、图示二、链表的概念及结构 链表是一种物理存储结构上非连续存储结构,数据
- 前言好久没有更新博客了,今天和大家分享一个关于emoji表情持久化问题,相信做web开发的都遇到过这样的问题,因为我们知道mysql的utf
- ListView如何实现简单列表,供大家参考,具体内容如下效果图:啥也没干的ListView张这样:fry.Activity01packag