java语言实现socket编程之BIO2(伪异步IO)
针对传统通讯的弊端(大量客户端,海量线程),这个问题得解决,jdk1.5以前是怎么处理的?
使用伪异步的形式去处理。它做的就是解决创建线程过多,服务器撑爆的这个事。实现技术也不难就是线程池配合队列来实现伪异步IO。需要用到的改变就是自定义线程池。自定义线程池,线程数量可控,不会无限创建线程。当然就不会撑爆了。
代码实现
客户端
package bio2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class BIOClient {
final static String ADDRESS = "127.0.0.1";
final static int PORT = 8000;
public static void main(String[] args) {
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
try {
socket = new Socket(ADDRESS,PORT);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
out.println("我是来自客户端的数据");
String resp = in.readLine();
System.out.println("client收到反馈: " + resp);
}catch (Exception e){
}finally {
if (in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服务端
package bio2;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class BIOServer {
final static int PORT = 8000;
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(PORT);
System.out.println("server start!");
Socket socket = null;
HandlerExecutorPool executorPool = new HandlerExecutorPool(50,100);
while (true){
//进行阻塞
socket = serverSocket.accept();
executorPool.execute(new ServerHandler(socket));
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
serverSocket = null;
}
}
}
自定义线程池
参数(50,100)执行过程说明:
我是8核心的U,若应对150客户端。设置100个队列长度。
先来八个请求,被8个可利用的线程处理。100个请求被队列所暂存。
剩下的42个,新启线程去处理。最大线程数不会超过50。
这种起线程的机制是有界阻塞队列决定的。
package bio2;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class HandlerExecutorPool {
private ExecutorService executorService;
public HandlerExecutorPool(int maxPoolSize,int QueueSize) {
this.executorService = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(),
maxPoolSize,
120L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(QueueSize)
);
}
public void execute(Runnable task){
this.executorService.execute(task);
}
}
业务handler
package bio2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class ServerHandler implements Runnable {
Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(), true);
String body = null;
while (true) {
body = in.readLine();
if (body == null) {
break;
}
System.out.println("body = " + body);
out.println("我来自服务器!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}