JAVA BIO的实现及原理分析
概念理解
一:理解同步:同步就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回,但是一旦调用返回,就得到返回值了。简单的为:就是由*调用者*主动等待这个*调用*的结果。
二:异步:*调用*在发出之后,这个调用就直接返回了,所以没有返回结果;换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。
生活案例
你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是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); 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关系;操作系统资源耗尽,服务端挂了;
一个客户一个服务员,多少个客户多少个服务员
图例