同步VS异步 阻塞VS非阻塞

来源:互联网 发布:安庆网络问政平台2017 编辑:程序博客网 时间:2024/05/18 00:54

一、问题来由

一个纯概念性问题,但是很常见,纠结N久,觉得需要写一篇文章来说一下。

二、概念

在比较这两个模式之前,我们首先的搞明白几个概念,什么是阻塞和非阻塞,什么是同步和异步?

同步和异步是针对应用程序和内核的交互而言的

同步:指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪
异步:是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知(异步的特点就是通知

而阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了就是站在当前线程角度说,线程是否被挂起,如果挂起就是阻塞,立即返回就是非阻塞

阻塞:读取或者写入函数将一直等待
非阻塞:读取或者写入函数会立即返回一个状态值

一般来说I/O模型可以分为:同步阻塞,同步非阻塞,异步(非阻塞)

三、IO组合

同步阻塞IO:

在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。JAVA传统的IO模型属于此种方式!

同步非阻塞IO:

在此种方式下,用户进程发起一个IO操作以后边可返回做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。

异步

异步既然是通知,那一定是非阻塞的。

这里写图片描述

四、Future

用一句话讲:future就是把 同步转异步

简单来讲,Future是这样一种Pattern:你提交一个异步的任务,比如提交到一个threadpool,与此同时拿到一个Future对象,任务的执行是异步的,这时候你可以去做其它的事情,等到异步任务结束的时候,你可通过前面的Future对象拿到异步执行的任务的结果。类似吃饭的时候领餐牌,饭煮好了可以拿餐牌换。

Future要获取异步任务执行的结果,需要通过轮询或者阻塞等待的方式,这样的方式,总显得不太‘完美’,我们知道,比较好的方式,应该是异步执行结束后,自动通知用户异步任务结束了,你可以通过Future来获取执行结果了。这就诞生了google的ListenableFuture,用户可以向它注册一个回调函数和提供一个线程池(可选),当异步任务执行结束后,它会自动在用户提供的线程池里调用用户注册的回调函数,通知用户异步任务执行结束了。当然,如果用户不提供线程池,它会在运行异步任务的工作线程里运行回调函数,这种情况适用于工作线程本身的任务比较轻量级的情景。


参考资料

[1] http://blog.csdn.net/kobejayandy/article/details/18059813

1 0
原创粉丝点击