同步阻塞IO模型是最简单的IO模型,用户线程在内核进行IO操作时如果数据没有准备号会被阻塞
![](https://github.com/AlgoricLi/MyImage/blob/master/IO/BIO.png?raw=true)
在BIO中,每次建立连接后,当线程调用read or write方法时,线程会被阻塞,直到有数据可读可写, 在此期间线程不能做其它事情。并且每次建立一个连接,都会创建一个线程进行读写,创建线程是需要消耗系统资源,在连接过多时,会撑爆系统。
BIO代码:
客户端:
public class Client {
private int port = 12345;
private static String serverIp = "localhost";
public Client(int port) {
this.port = port;
}
public void send() {
Scanner sc = new Scanner(System.in);
try (Socket socket = new Socket(serverIp, port);
//创建流
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
System.out.println("请输入一个数字:");
int a = sc.nextInt();
//向服务端写入数据
out.println(a);
//读取服务端返回结果
System.out.println("服务端结果为:" + in.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务端
public class Server {
//单例
private static ServerSocket serverSocket;
public synchronized static void start(int port) throws IOException {
if(serverSocket != null) return;
try {
serverSocket = new ServerSocket(port);
System.out.println("服务器已启动,端口号:" + port);
Socket socket;
//死循环监听
while (true) {
//监听到客户端通信建立连接,完成三次握手
socket = serverSocket.accept();
//每次建立连接开启线程处理
new Thread(new ServerHandle(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally{
//一些必要的清理工作
if(serverSocket != null){
System.out.println("服务器已关闭。");
serverSocket.close();
serverSocket = null;
}
}
}
}
测试通信:
public class Test {
public static void main(String[] args) throws InterruptedException {
//运行服务器
new Thread(new Runnable() {
@Override
public void run() {
try {
//ServerForPool.start(12345);
Server.start(12345);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(100);
Client client = new Client(12345);
client.send();
}
}
上面说了这种情况非常消耗资源,可以稍微改进一下,加个线程池,这样就不会无限创建线程处理连接:
public class ServerForPool {
private static int port = 12345;
private static ServerSocket serverSocket;
private static ExecutorService executorService = Executors.newFixedThreadPool(60);
public synchronized static void start(int port) throws IOException {
if(serverSocket != null)
return;
try {
serverSocket = new ServerSocket(port);
System.out.println("服务器已启动:" + port);
Socket socket;
while (true) {
socket = serverSocket.accept();
executorService.execute(new ServerHandle(socket));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(serverSocket != null){
System.out.println("服务器已关闭。");
serverSocket.close();
serverSocket = null;
}
}
}
}