背景介绍
众所周知,讲到IO,离不开这四个名词:同步、异步、阻塞、非阻塞。在《Operating System Concepts [9th Edition]》书中描述对这种进程间通信进行了一些描述。
简单来说,阻塞和非阻塞也可以称之为同步和异步,其行为本质是一样的,都是下面四种操作的组合:
- Blocking send 阻塞发送,直到数据被接收进程读取;
- NonBlocking send 非阻塞发送,发送以后,可以处理其他事务;
- Blocking receive 阻塞接收,接收器一直阻塞,直到有数据为止;
- NonBlocking receive 非阻塞接收,无论有无数据,接收器都可以检索读取;
在我理解看来,**阻塞非阻塞,关注的是否挂起等待消息执行,也就是send方法;同步异步,关注的是请求结果的通知机制,也就是receive方法。**例如方法a执行时,其中有一行是调用了方法b,阻塞是要等b执行完成以后再执行后续的代码块;非阻塞是把b抛给其他线程执行以后,立马执行后续代码块。
按照这个背景知识,我们可以进行下面四种组合:
同步阻塞
【Blocking send】+ 【Blocking receive】,阻塞发送 + 阻塞接收
int response = Rpc_methodB();
// 拿到执行的结果,做特定的操作
print("do specify. response="+response);
// 做其他事情
print("do other things");
同步非阻塞
【NonBlocking send】+ 【Blocking receive】,非阻塞发送 + 阻塞接收
可以参考轮询模式,提交请求以后,轮询读取结果
Futher responseFuther = threadPool. submit(Rpc_methodB());
// 不等待,有无结果都拿取一次
Integer response = responsefuther. getNow();
if(response != null){
// 拿到执行的结果,做特定的操作
print("do specify. response="+response);
}
// 做其他事情
print("do other things 1");
// 做其他事情
print("do other things 2");
// 做其他事情
print("do other things 3");
// 方法最后再尝试获取结果
Integer response = responsefuther. get();
if(response != null){
// 拿到执行的结果,做特定的操作
print("do specify. response="+response);
}
异步阻塞
【Blocking send】+ 【NonBlocking receive】,阻塞发送 + 非阻塞接收
// 除非是生产消费模式,否则蠢蠢的
Rpc_methodB();
threadPool. submit(()->{
for(;;){
// Rpc_methodB方法将结果写到一个共享变量中
Integer response = getResponseNow();
if (response != null){
// 拿到执行的结果,做特定的操作
print("do specify. response="+response);
}
}
});
// 做其他事情
print("do other things");
异步非阻塞
【NonBlocking send】+ 【NonBlocking receive】,非阻塞发送 + 非阻塞接收
threadPool. submit(Rpc_methodB()).listener(r,e -> {
if(e == null) {
int response = r;
// 拿到执行的结果,做特定的操作
print("do specify. response="+response);
// 做其他事情
print("do other things");
}
})