漫谈Java IO之基础篇
Java的网络编程如果不是专门搞服务器性能开发或者消息分发,几乎可能涉及不到。但是它却是面试找工作必问的一个知识点,涵盖的知识体系也非常广泛,从Java底层IO原理到操作系统内核组成,再到网络TCP、UDP、HTTP的应用实践....因此,即便是职场多年的老油条,仍然需要时刻复习,更别提我这种只有七秒钟记忆的小菜鸟了。
Java网络IO的演化,从最开始JDK1.4之前是基于阻塞的IO;发展到1.4发布后的Nio提供了selector多路复用的机制以及channel和buffer,再到1.7的NIO升级提供了真正的异步api;再发展到后来崭露头角的MINA和Netty。因此整个网络IO编程的学习整理,也会按照下面的几个步骤来进行:
- 网络IO的基本知识与概念
- 普通IO以及BIO服务器
- NIO的使用与服务器Hello world
- Netty入门与服务器Hello world
- Netty深入浅出
今天就简单的了解下网络IO需要具备的基本知识与概念。
同步、异步和阻塞、非阻塞
经常听人提起,同步阻塞服务器或者异步非阻塞服务器,网上有很多的文章针对这个概念作出了讲解,每个人理解的貌似都不太一样。最容易把异步和非阻塞搞混....我这里简单的说下自己的理解:
同步synchronous、异步asynchronous,他们的区别就是发起任务后,本身的一个状态——如果是一直等待结果,那就是同步;如果立即返回,并采用其他的方式得到结果就是异步(比如,状态、通知、回调)。
举个例子:
- 在过去科技不发达的时候,银行取钱都是排队的模式。想取钱就得去排队,直到轮到自己,这就是同步;
- 现在去银行一般直接叫号,然后去休息位置休息打游戏,登到轮到自己的时候,会有通知,这就是异步;
阻塞blocking、非阻塞non-blocking,则聚焦的是CPU在等待结果的过程中的状态。比如前面的例子,排队的过程中什么也不做就是阻塞;一边排队,一遍玩王者荣耀就是非阻塞的。
用户空间与内和空间
这个概念就涉及操作系统了,为了保护操作系统的安全,会将内存分为用户空间和内核空间两个部分。如果用户想要操作内核空间的数据,需要把数据从内和空间拷贝到用户控件。
举个例子:
服务器接收客户端发过来的请求,想要进行处理,大致会经过下面几个步骤:
- 服务器的网络驱动接收到消息,去内核上申请空间;并等待完整的数据包到达(有可能分组传送,没传完...),复制到内核空间;
- 数据从内核空间拷贝到用户空间
- 用户程序进行处理
因此大致可以把接收消息理解为两个阶段:1. 等待数据到达 2. 拷贝到用户空间
了解了这个过程,就能明白为什么会出现经典的5大网络模型了.
五大网络模型
这几个网络模型还是学生时代的时候也看过,但是理解的不够透彻,也不知道到底有什么区别。最近网上也看过不少的文章,发现有一些文章引用的小例子不错,能很简单的了解这些模型的意思。所以我这边也借鉴一下:
在大连高新万达后面有一条叫做金街的小吃街,有一个露天的路边摊叫做“小红旗”,主要是做炸臭豆腐和冷面,然后用冷面把臭豆腐卷起来,刷上臭烘烘的酱料,非常好吃。每次路过都能看到不少人在排队,队伍长的有种想让人辞职加盟的感觉....基本上排个队伍都得半个小时-一个小时吧。
这个排队的过程,明显就是上面所说的同步阻塞模式....那我这边就设想下,如果小红旗的生意做大了,可以怎么发展?正好套用下网络模型的概念...
1. 同步阻塞IO
这个就不详细说了,排队的过程哪也去不了,如果你还没有带手机,排队的过程中就只能干瞪眼了。这就是很明显的同步+阻塞模式。
2. 同步非阻塞IO
如果小红旗的老板搞了一个点菜机,来点单的顾客把自己想吃的划上,然后等着老板去做,自己可以在这一个小时的时间里去周围商场溜达下。但是由于没有任何通信方式,只能不停的回来问老板,做好了没有。
回来询问的时间是由顾客自己掌控的,如果时间很短,那么可以尽量早的知道臭豆腐炸好没,但是也会影响逛街的体验;如果时间很长,有可能臭豆腐早就做好了..结果放的时间长了,反而不好吃了。
因此非阻塞IO基于状态轮训的方式,虽然能让程序在等待的过程中做点其他的事情,但是频繁的切换运行程序,反而会造成很大的压力。
3. IO多路复用/事件驱动
小红旗老板升级了系统,放弃使用点菜机,改用麦当劳那种点餐大屏。同样是点餐,但是一个大屏里面显示了很多人的臭豆腐进度,即节省了资源,也避免大家不停的询问。
其实Nio活着Netty就是基于这种模式,一个线程就可以监听很多IO操作,这样在IO等待上就高效多了。具体实现是依赖于操作系统的,windows和linux都有不同的实现方式。最初的select或者poll,都有并发数的限制,并且NIO的select还有空轮训的问题;epool则突破了连接数的限制,一个线程就可以监听大量的IO操作。这个感兴趣的朋友,可以深入了解下select、poll、epool的原理。
4. 信号驱动IO
小红旗老板又时髦了,搞了一个升级版的美味不用等。顾客基于微信小程序点菜,菜做好了自动提醒顾客取餐....这个提醒的过程,就像是发射了一个特殊的信号。
不过UNIX网络编程里面的信号驱动,可没这么简单,这个信号是依赖于操作系统底层的,捕获信号或者处理都很麻烦,所以现在应用的也不是很广泛。
5. 异步非阻塞IO
一对小情侣李雷和韩梅梅,韩梅梅口味很重,特别喜欢吃臭豆腐,但是李雷完全不感兴趣,闻到味道就想吐。于是李雷就跟韩梅梅约定,让韩梅梅自己去吃,李雷跑到旁边的咖啡厅喝咖啡。韩梅梅自己去排队买臭豆腐,买完顺便吃完,然后回来找李雷....
这个过程就是异步非阻塞的,消息的等待和处理都在服务器端完成,用户只要最后接收到消息处理完的通知就行了。
总结
总结来说,这几种网络模型:
- 同步阻塞:强调的是我要做! —— 别的啥也别说,就是要做!
- 同步非阻塞:强调的是我想做! —— 在想的过程中,干点其他的事情更好。
- 异步非阻塞:强调的是我做完了!—— 等得到结果通知的时候,工作已经做完了。
其中细节,还需慢慢体会...后面的文章将会挑几个模型做代码的演示,更多内容还请持续关注。
参考
- 并发编程网
- Netty源码分析
- Netty源码分析
- Netty源码分析
- IO多路复用之select、poll、epoll
- 聊聊Linux五种IO模型
- 聊聊同步、异步、阻塞、非阻塞
- Netty官方文档
- 一篇文章,读懂Netty的高性能架构之道
- 代码示例分享
漫谈Java IO之基础篇的更多相关文章
- Java多线程系列--“基础篇”11之 生产消费者问题
概要 本章,会对“生产/消费者问题”进行讨论.涉及到的内容包括:1. 生产/消费者模型2. 生产/消费者实现 转载请注明出处:http://www.cnblogs.com/skywang12345/p ...
- Java多线程系列--“基础篇”04之 synchronized关键字
概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...
- Java多线程系列--“基础篇”02之 常用的实现多线程的两种方式
概要 本章,我们学习“常用的实现多线程的2种方式”:Thread 和 Runnable.之所以说是常用的,是因为通过还可以通过java.util.concurrent包中的线程池来实现多线程.关于线程 ...
- Java多线程系列--“基础篇”03之 Thread中start()和run()的区别
概要 Thread类包含start()和run()方法,它们的区别是什么?本章将对此作出解答.本章内容包括:start() 和 run()的区别说明start() 和 run()的区别示例start( ...
- Java多线程系列--“基础篇”05之 线程等待与唤醒
概要 本章,会对线程等待/唤醒方法进行介绍.涉及到的内容包括:1. wait(), notify(), notifyAll()等方法介绍2. wait()和notify()3. wait(long t ...
- Java多线程系列--“基础篇”06之 线程让步
概要 本章,会对Thread中的线程让步方法yield()进行介绍.涉及到的内容包括:1. yield()介绍2. yield()示例3. yield() 与 wait()的比较 转载请注明出处:ht ...
- Java多线程系列--“基础篇”07之 线程休眠
概要 本章,会对Thread中sleep()方法进行介绍.涉及到的内容包括:1. sleep()介绍2. sleep()示例3. sleep() 与 wait()的比较 转载请注明出处:http:// ...
- Java多线程系列--“基础篇”08之 join()
概要 本章,会对Thread中join()方法进行介绍.涉及到的内容包括:1. join()介绍2. join()源码分析(基于JDK1.7.0_40)3. join()示例 转载请注明出处:http ...
- Java多线程系列--“基础篇”09之 interrupt()和线程终止方式
概要 本章,会对线程的interrupt()中断和终止方式进行介绍.涉及到的内容包括:1. interrupt()说明2. 终止线程的方式2.1 终止处于“阻塞状态”的线程2.2 终止处于“运行状态” ...
随机推荐
- 利用 xrandr 命令修改屏幕分辨率
问题背景 电脑外接着一个 23' 的显示器,分辨率为 1920*1080. 操作系统:ubuntu 14.04 今天,通过 Setting->Displays 中选择外接屏的分辨率时,发现最大只 ...
- 笔记+R︱信用风险建模中神经网络激活函数与感知器简述
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 本笔记源于CDA-DSC课程,由常国珍老师主讲 ...
- R语言︱list用法、批量读取、写出数据时的用法
列表是一种特别的对象集合,它的元素也由序号(下标)区分,但是各元素的类型可 以是任意对象,不同元素不必是同一类型.元素本身允许是其它复杂数据类型,比如,列表 的一个元素也允许是列表.例如: > ...
- vxWorks BSP主要文件目录的组成及主要文件的作用
vxWorks BSP主要文件目录的组成及主要文件的作用 1.目录target/config/All: 这个目录下的文件是所有BSP文件共享的,不是特别需要不要更改里面的任何文件. a.configA ...
- Java获取某年某月的最后一天
Java获取某年某月的最后一天 1.设计源码 LastDayOfMonth.java: /** * @Title:LastDayOfMonth.java * @Package:com.you.free ...
- ZigBee技术
ZigBee技术是一种近距离.低复杂度.低功耗.低速率.低成本的双向无线通讯技术.主要用于距离短.功耗低且传输速率不高的各种电子设备之间进行数据传输以及典型的有周期性数据.间歇性数据和低反应时间数据传 ...
- 百度地图JavaScript API经纬度查询-MAP
百度地图JavaScript API经纬度查询-MAP-ABCDEFGHIJKMHNOPQRSTUVWXYZ: 搜索:<input type="text" size=&quo ...
- CentOS中配置NFS服务
1.服务器端安装rpcbind.nfs-utils.nfs-server包 yum install nfs-utils -y 2.修改服务器端配置文件,添加需要共享的文件夹. vim /etc/exp ...
- 为Android Studio中的SettingsActivity定制任务栏
Android Studio为开发者提供了很多内建的Activity, 其中Settings Activity是非常有用且功能强大的一种内建Activity. Setting Activity其实本质 ...
- springboot--springboot+mybatis多数据源最简解决方案
说起多数据源,一般都来解决那些问题呢,主从模式或者业务比较复杂需要连接不同的分库来支持业务.我们项目是后者的模式,网上找了很多,大都是根据jpa来做多数据源解决方案,要不就是老的spring多数据源解 ...