1 代碼
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 傳統socket服務端-多線程
*/
public class OioServer2 {
@SuppressWarnings("resource")
public static void main(String[] args) throws Exception {
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
// 創建socket服務,監聽10101端口
ServerSocket server = new ServerSocket(10101);
System.out.println("服務器啓動!");
while (true) {
// 獲取一個套接字【阻塞】
final Socket socket = server.accept();
System.out.println("一個新客戶端連接!");
newCachedThreadPool.execute(new Runnable() {
public void run() {
// 異步業務處理。客戶端1執行至此,不阻塞。server可以接收客戶端2的連接
handler(socket);
}
});
}
}
/**
* 讀取數據
*/
public static void handler(Socket socket) {
try {
byte[] bytes = new byte[1024];
InputStream inputStream = socket.getInputStream();
while (true) {
// 讀取數據【阻塞】
int read = inputStream.read(bytes);
if (read != -1) {
System.out.println(new String(bytes, 0, read));
} else {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
System.out.println("socket關閉");
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2 測試流程
原阻塞代碼accept和read不變,但客戶端1執行異步業務處理,不阻塞,server可以接收客戶端2的連接。這種模式爲一個客戶端一個線程,會導致線程數過多。相當於一個飯店,經理在門口迎接客人(accept),相當於爲每個客戶(socket)安排一個服務員(線程)。