文档章节

OkHttp完全解析(三)并发

k
 kim366
发布于 2016/05/13 19:08
字数 1452
阅读 27
收藏 0

HttpURLConnection 的API是阻塞是的API,通过创建一个写入阻塞发送一个请求,通过一个读取阻塞接受响应。

[源码分析:4.2] 框架连接FramedConnection

 

4.1 阻塞式API

阻塞式API因其自上而下的程序代码而显得方便实用。网络调用跟其他普通方法调用一样:请求数据,返回。如果请求失败,则获得一个指向调用的堆栈跟踪。

阻塞式API可能会很低效,因为等待网络期间,线程处于闲置状态。但是线程是昂贵的,因为其建立在内存和上下文之上。

4.2 框架协议Framed Protocol 

框架协议根spdy/3和http/2一样,不会导致自身阻塞API。每个应用层线程都希望因为特定流阻塞I/O,但是在Socket中,流是多路复用的。线程不允许直接和socket对话,而是要与共享这个socket的其他应用层线程合作。在单个阻塞线程上,直接实现spdy/3或者http/2的框架规则是不切实际的。流控制特性在读取和写入之间引进反馈,要求写入告知读取,读取节制写入。

OkHttp中,在框架协议上暴露了阻塞API,这篇文档解释了使其工作的代码和原理。

注:SPDY(读作“SPeeDY”): Google开发的基于TCP的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。(参见附件《SPDY》)

 

4.3 线程

4.3.1 应用的线程调用

应用层必须阻塞写入I/O,在我们将字节写入到socket之前,不能从一个写入中返回。否则,如果写入失败,我们将无法把一个IOException传递到应用中。我们应该告知应用层是否写入成功或者失败。

应用层也可以阻塞写入操作。如果应用程序请求从一个没有任何东西的地方读取数据,则需要持有那个线程,直到字节到达,流关闭,或者超时消逝。如果持有一些字节,但是没有任何其他地方需要他们,则应该将其放置到缓冲区中。从流量控制方面讲,在他们被应用消费掉之前,不应认为被传递出去了。假设有一个基于http/2的视频流。假设用户暂停了媒体播放,应用停止从流中读取字节。这个时候缓冲区会被填满,流控制会阻止服务器再往这个流中发送数据。当用户继续播放视频流时,缓冲区会被排放,读取被确认,服务端继续流出数据。

4.3.2 共享读取线程

不能依赖应用线程从socket中读取数据。应用线程是短暂的: 有时候,他们正在读取或者写入数据,有时候,他们停止做有关于应用层的事情。但是socket是永久的,并且需要持续的关注,比如我们分发所有进入的框架帧,以使应用层需要它时连接正常。

所以,我们为每个socket创建专用线程,专门读取框架帧并分发他们。

读取线程始终不应运行应用层代码。否则,一个缓慢的流就会拦截整个连接。

同样的,读取线程始终不应该阻塞写操作,否则可能导致锁死连接。试想,客户端和服务端都违反了这个规则。那么,如果运气不好的话,他们会填满整个TCP缓冲区(导致写阻塞),然后使用它们的读取线程进行去写入帧。没有其他地方从另一端读取数据,缓冲区也会被消耗完。

4.3.3 Do-stuff-later pool 

有时候,会存在调用应用层或者响应一个ping操作的动作,而发现这个工作的线程和应该处理这些工作的线程不一致。我们就会在线程池中加入一个线程对象,并且由线程池中的另一个线程进行处理。

4.4 锁

有三种不同的事件同步。

4.4.1  SpdyConnection

这种锁会守护每个连接的内部状态。这种锁不阻塞操作。这就意味着,我们获取一个锁,读取或者写入一些属性,然后释放锁。而没有I/O和应用层回调。

4.4.2  SpdyStream

这种锁会守护每个流的内部状态。跟上面一样,是不阻塞操作。当我们需要持有一个应用线程阻塞读操作时,我们必须通知或者等待这个锁。因为当wait()处于等待状态时,这个锁会被释放。

4.4.3  FrameWriter

   Socket的写是被FrameWriter守护的。同一时刻只有一个流可以写入,所以消息不交叉。写操作要么由应用层线程完成,要么由填充池完成。

4.5 持有多重锁

持有一个FrameWriter锁的同时,你可以持有一个SpdyConnection锁。但是,反过来不可以。因为持有一个FrameWriter锁可能引起阻塞。对于记账本来说,在创建一个流的时候这样做是有必要的。好的框架,要求在socket中,流的ID是连续的,所以我们需要和发送的流框架绑定设定的ID。

本文转载自:http://blog.csdn.net/oyangyujun/article/details/50039253

共有 人打赏支持
k
粉丝 1
博文 129
码字总数 0
作品 0
朝阳
私信 提问
Android技能树 — 网络小结之 OkHttp超超超超超超超详细解析

前言: 本文也做了一次标题党,哈哈,其实写的还是很水,各位原谅我O(∩_∩)O。 介于自己的网络方面知识烂的一塌糊涂,所以准备写相关网络的文章,但是考虑全部写在一篇太长了,所以分开写,...

青蛙要fly
11/13
0
0
Android中流行的第三方库资源收集

1、GSON GSON是将JSON解析成POJO的Java库。GSON也可以将POJO解析成JSON。 2、OkHttp OKHttp是Android版Http客户端。非常高效,支持SPDY、连接池、GZIP和 HTTP 缓存。默认情况下,OKHttp会自动...

jdroid
2014/05/02
0
0
说说在 Android 中如何发送 HTTP 请求

客户端会向服务器发出一条 HTTP 请求,服务器收到请求后会返回一些数据给客户端,然后客户端再对这些数据进行解析与处理。 1 HttpURLConnection 可以使用 HttpURLConnection(官方推荐) 来发...

deniro
06/09
0
0
feign和okhttp的结合

背景 使用feign可以很方便的调用各种http接口 http请求神器之Feign 那么feign是如何做到的呢? 分析 本质上默认场景feign仍然是使用httpClient进行调用的。 通过声明式的RequestMapping等注解...

Mr_Qi
07/11
0
0
Android Okhttp缓存:精细化每一个Request的CacheControl缓存控制策略(二)

Android Okhttp缓存:精细化每一个Request的CacheControl缓存控制策略(二) 之前我写的附录文章1,只是简单的使用缺省的方法实现Okhttp的缓存。现在使用CacheControl,精细化到每一个Reque...

开开心心过
2017/10/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

崛起于Springboot2.X之通讯WebSocket(40)

技术简介:Springboot2.0.3+freemaker+websocket 1、添加pom依赖 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-bo......

木九天
18分钟前
1
0
Java常用四大线程池用法以及ThreadPoolExecutor详解

为什么用线程池? 1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处-理效率 2.线程并发数量过多,抢占系统资源从而导致阻塞 3.对线程进行一些简单的管理 在Java中...

孟飞阳
20分钟前
1
0
Netty+Websocket 实现一个简易聊天室

后台代码 /** * 服务端 */public class ChatServer {public static void main(String[] args) throws Exception {int port=8080; //服务端默认端口new ChatServer().bind...

这很耳东先生
22分钟前
2
0
一个本科学生对Linux的认知

我是一名大三的普通一本大学的软件工程的一名学生,学校开设了一些关于系统开发的课程,纸上得来终觉浅,学校的课程课时较短,想要在56个课时之内学会一些公司需要的技能,无疑是纸上谈兵,一...

linuxprobe16
24分钟前
1
0
如何选择开源许可证?

如何为代码选择开源许可证,这是一个问题。 世界上的开源许可证,大概有上百种。很少有人搞得清楚它们的区别。即使在最流行的六种----GPL、BSD、MIT、Mozilla、Apache和LGPL----之中做选择,...

吴伟祥
25分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部