您的位置:首页 > 编程语言 > Java开发

JAVA BIO的实现及原理分析

2018-01-21 17:05 363 查看
概念理解

一:理解同步:同步就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回,但是一旦调用返回,就得到返回值了。简单的为:就是由*调用者*主动等待这个*调用*的结果。

二:异步:*调用*在发出之后,这个调用就直接返回了,所以没有返回结果;换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。
生活案例

你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。

而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

三:阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
四:阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

还是上面的例子,
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。
在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。

问题一:网络编程是什么?

两个进程之间的通讯;客户端和服务端之间的通讯;
问题二:你对传统的BIO的理解是什么?

笔者的理解:一对应 一请求 一应答模式程


传统Socket阻塞案例代码

 

public classTraditionalSocketDemo{

@SuppressWarnings("resource")

public static voidmain(String[]
args)throwsIOException
{

ServerSocket serverSocket =newServerSocket(7777);

System.out.println("服务端启动...");

while(true){

// 获取socket套接字

// accept()阻塞点

Socket socket = serverSocket.accept();

System.out.println("有新客户端连接上来了...");

// 获取客户端输入流

InputStream is = socket.getInputStream();

byte[]
b = new byte[1024];

while(true){

// 循环读取数据

// read() 阻塞点

intdata
= is.read(b);

if(data
!= -1){

String info =newString(b,0,data,"GBK");

System.out.println(info);

}else{

break;

}

}

}

}

}

模拟服务端请求:telnet
127.0.0.1:7777
在debugger代码的过程中会发现:服务端启动,只有当客户端就绪后才进行下一步操作(如果客户端没有就绪,线程阻塞),客户端发送请求,程序才继续往下执行,如果客户端没有发出请求,线程阻塞;
上面的代码有两个阻塞点:
①等待客户端就绪;
②等待客户端发送请求;
图例分析




传统bio多线程版本

public class TraditionalSocketDemo2{
@SuppressWarnings("resource")

public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(7777);
System.out.println("服务端启动...");
while(true){
// 获取socket套接字
// accept()阻塞点
Socket socket = serverSocket.accept();
System.out.println("有新客户端连接上来了...");
new Thread(new Runnable() {
@Override
public void run() {
try {
// 获取客户端输入流
InputStream is = socket.getInputStream();
byte[] b = new byte[1024];
while(true){
// 循环读取数据
// read() 阻塞点
int data = is.read(b);

a3c0
if(data != -1){
String info = new String(b,0,data,"GBK");
System.out.println(info);
}else{
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
}


 能够解决传统的BIO问题,但是会出现:多少个客户端多少个线程,请求和线程的个数1:1关系;操作系统资源耗尽,服务端挂了;

一个客户一个服务员,多少个客户多少个服务员

图例

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息