OkHttp3源码详解之Okhttp任务队列工作原理(三)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680
1 概述
1.1 引言
android
完成非阻塞式的异步请求的时候都是通过启动子线程的方式来解决,子线程执行完任务的之后通过handler
的方式来和主线程来完成通信。无限制的创建线程,会给系统带来大量的开销。如果在高并发的任务下,启用个线程池,可以不断的复用里面不再使用和有效的管理线程的调度和数量的管理。就可以节省系统的成本,有效的提高执行效率。
1.2 线程池ThreadPoolExecutor
okhttp的线程池对象存在于Dispatcher类中。实例过程如下
1.2 Call对象
了解源码或使用过okhttp
的都知道。 okttp
的操作元是Call对象。异步的实现是RealCall.AsyncCall
。而 AsyncCall
是实现的一个Runnable
接口。
所以Call本质就是一个Runable
线程操作元肯定是放进excutorService中直接启动的。
2 线程池的复用和管理
2.1 图解
为了完成调度和复用,定义了两个队列分别用作等待队列和执行任务的队列。这两个队列都是Dispatcher
成员变量。Dispatcher是一个控制执行,控制所有Call的分发和任务的调度、通信、清理等操作。这里只介绍异步调度任务。
在《okhttp连接池复用机制》文章中我们在缓存Connection连接的时候也是使用的Deque双端队列。这里同样的方式,可以方便在队列头添加元素,移除尾部的元素。
2.2 过程分析
Call
代用equeue
方法的时候
方法中满足执行队列里面不足最大线程数maxRequests
并且Call对应的host数目不超过maxRequestsPerHost
的时候直接把call对象直接推入到执行队列里,并启动线程任务(Call
本质是一个Runnable
)。否则,当前线程数过多,就把他推入到等待队列中。Call
执行完肯定需要在runningAsyncCalls
队列中移除这个线程。那么readyAsyncCalls
队列中的线程在什么时候才会被执行呢。
追溯下AsyncCall
线程的执行方法
这里做了核心request的动作,并把失败和回复数据的结果通过responseCallback
回调到Dispatcher。执行操作完毕了之后不管有无异常都会进入到dispactcher
的finished
方法。
在这里call在runningAsyncCalls队列中被移除了,重新计算了目前正在执行的线程数量。并且调用了promoteCalls()
看来是来调整任务队列的,跟进去看下
原来实在这里对readyAsyncCalls
进行调度的。最终会在readyAsyncCalls
中通过remove
操作把元素迭代取出并移除之后加入到runningAsyncCalls的执行队列中执行操作。ArrayDeque
是非线程安全的所以finished
在调用promoteCalls
的时候都在synchronized
块中执行的。执行等待队列线程当然的前提是runningAsyncCalls
线程数没有超上线,而且等待队列里面有等待的任务。
以上完成了线程线程池的复用和线程的管理工作。
小结,Call在执行任务通过Dispatcher把单元任务优先推到执行队列里进行操作,如果操作完成再执行等待队列的任务。
原文链接:https://www.bbsmax.com/A/VGzlBLg85b/
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680
原文地址:https://www.cnblogs.com/Android-Alvin/p/12102846.html
- cookie、session、token三者使用
- SpringCloud注册中心集群搭建
- SpringCloud配置中心集群搭建
- HDU1846 Brave Game
- 拉格朗日插值
- python爬虫入门(二)Opener和Requests
- python爬虫入门(三)XPATH和BeautifulSoup4
- python爬虫入门(四)利用多线程爬虫
- LOJ #115. 无源汇有上下界可行流
- 数据库改名系列(数据库名,逻辑名,物理文件名)
- BZOJ1468: Tree
- 洛谷P3806 【模板】点分治1
- 探索ASP.NET MVC5系列之~~~5.缓存篇(页面缓存+二级缓存)
- 洛谷P3383 【模板】线性筛素数(Miller_Rabin)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 解决npm install时报错无法安装chromedriver的问题
- 解决集成jpa时无法创建entityManagerFactory的问题
- Spring船新版推出的WebFlux,是兄弟就来学我
- JDK9特性-Reactive Stream 响应式流
- Java函数式编程之Stream流编程
- 使用docker安装elasticsearch伪分布式集群以及安装ik中文分词插件
- PyQt5 技巧篇-如何让窗体只显示关闭按钮
- Gradle多项目构建与jar包发布
- Gradle初体验
- hexo初始化
- 容器部署Spring Cloud项目
- Python 爬虫篇-爬取网页中的图片,图片爬取实例演示。
- Python 爬虫进阶篇-4行代码实现爬取指定网站中的全部图片,深入剖析
- Python+selenium 自动化-基本环境搭建
- Java多线程与并发笔记