調用者主動等待調用的結果
簡介
早期的jdk中,采用BIO通信模式:
通常有一個acceptor(消費者) 去負責監聽客戶端的連接。
它接收到客戶端的連接請求之后為每個客戶端創建一個線程進行鏈路處理,處理完成之后,線程銷毀。
一個客戶端連接,對應一個處理線程。他們之間的對應關系是 1:1。
由于客戶端連接和服務端的處理之間的對應關系是1:1,如果遇到任務比較大,處理比較慢。
或者并發量比較大的情況下,系統會創建大量的線程。從而導致服務器線程暴增,性能急劇下降,甚至宕機。
客戶端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
try {
//創建連接
socket = new Socket("127.0.0.1", 8080);
//輸出流:發送數據
out = new PrintWriter(socket.getOutputStream(), true);
out.println("發送數據");
//輸入流:接收數據
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//阻塞:未收到數據就等在這里
String resp = in.readLine();
System.out.println("回應:" + resp);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
out.close();
out = null;
}
}
}
服務端
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
//創建服務端
serverSocket = new ServerSocket(8080);
Socket socket = null;
while (true) {
//從socket的隊列中獲取socket的連接
//相當于一個消費者
///當前的線程阻塞在accept方法上面。該方法一直阻塞,除非獲取到socket連接返回
socket = serverSocket.accept();
// 獲得到socket連接之后,分配線程任務進行處理
new Thread(new Handler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
serverSocket = null;
}
}
}
}
處理線程
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
//輸入流:接收數據
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
//接收數據
String receive = null;
//輸出流:發送數據
out = new PrintWriter(this.socket.getOutputStream(), true);
//回應結果
String currentTime = null;
while (true) {
//輸入流:讀取數據的部分是阻塞的
//由于使用的是阻塞IO,那么read方法一直處于阻塞狀態,要等到數據傳送完成才結束(返回-1)
//1,內核程序從網卡中把數據讀取到內核空間中,是一直阻塞的。
//2,用戶程序把內核空間的數據復制到用戶空間的過程,是阻塞的。
//這兩個過程中,對應的程序部分就是read方法的阻塞
receive = in.readLine();
if (receive == null) {
break;
}
System.out.println(receive);
//輸出流:輸出數據
currentTime = "收到";
out.println(currentTime);
}
} catch (IOException e) {
e.printStackTrace();
if (in != null) {
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (out != null) {
out.close();
out = null;
}
}
}
}