几个概念
阻塞IO 和非阻塞IO 这两个概念是程序级别的。主要描述的是程序请求操作系统IO操作后,如果IO资源没有准备好,那么程序该如何处理的问题:前者等待;后者继续执行(但是使用线程一直轮询,直到有IO资源准备好了)。
同步IO 和 异步IO,这两个概念是操作系统级别的。主要描述的是操作系统在收到程序请求IO操作后,如果IO资源没有准备好,该如何响应程序的问题:前者不响应,直到IO资源准备好以后;后者返回一个标记(好让程序和自己知道以后的数据往哪里通知),当IO资源准备好以后,再用事件机制返回给程序。
同步阻塞模式(Blocking IO)
同步阻塞IO模型是最简单的IO模型,用户线程在内核进行IO操作时如果数据没有准备号会被阻塞。
Java同步阻塞模式
Java中的阻塞模式BIO,就是在java.net包中的Socket套接字的实现,Socket套接字是TCP/UDP等传输层协议的实现。
Java同步阻塞模式编码
多线程客户端
为了测试服务端程序,可以先编写一个多线程客户端用于请求测试。
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.concurrent.CountDownLatch; /** * <p> * BIO测试 * 模拟20个客户端并发请求,服务端则使用单线程。 * * @Author niujinpeng * @Date 2018/10/15 10:50 */ public class SocketClient { public static void main(String[] args) throws InterruptedException { Integer clientNumber = 20; CountDownLatch countDownLatch = new CountDownLatch(clientNumber); // 分别启动20个客户端 for (int index = 0; index < clientNumber; index++, countDownLatch.countDown()) { SocketClientRequestThread client = new SocketClientRequestThread(countDownLatch, index); new Thread(client).start(); } synchronized (SocketClient.class) { SocketClient.class.wait(); } } } /** * <p> * 客户端,用于模拟请求 * * @Author niujinpeng * @Date 2018/10/15 10:53 */ class SocketClientRequestThread implements Runnable { private CountDownLatch countDownLatch; /** * 线程的编号 */ private Integer clientIndex; public SocketClientRequestThread(CountDownLatch countDownLatch, Integer clientIndex) { this.countDownLatch = countDownLatch; this.clientIndex = clientIndex; } @Override public void run() { Socket socket = null; OutputStream clientRequest = null; InputStream clientResponse = null; try { socket = new Socket("localhost", 83); clientRequest = socket.getOutputStream(); clientResponse = socket.getInputStream(); //等待,直到SocketClientDaemon完成所有线程的启动,然后所有线程一起发送请求 this.countDownLatch.await(); // 发送请求信息 clientRequest.write(("这是第" + this.clientIndex + "个客户端的请求").getBytes()); clientRequest.flush(); // 等待服务器返回消息 System.out.println("第" + this.clientIndex + "个客户端请求发送完成,等待服务器响应"); int maxLen = 1024; byte[] contentBytes = new byte[maxLen]; int realLen; String message = ""; // 等待服务端返回,in和out不能cloese while ((realLen = clientResponse.read(contentBytes, 0, maxLen)) != -1) { message += new String(contentBytes, 0, realLen); } System.out.println("第" + this.clientIndex + "个客户端接受到来自服务器的消息:" + message); } catch (IOException e) { e.printStackTrace(); }

