上次的服务端一次只能接受一个客户端的连接,性能实在堪忧,我们对服务端进行了改造,
每接到一个客户端的请求,就新建一个线程,让新线程跟客户端进行交互,主线程可以继续等待其他客户端的连接。
服务端:
public class Server { public static void main(String[] args) throws Exception { System.out.println("==服务器的启动=="); // 1.注册端口 ServerSocket serverSocket = new ServerSocket(8888); while (true) { //2.每接收到客户端的连接,就新建一个线程进行处理 Socket socket = serverSocket.accept(); new ServerReadThread(socket).start(); System.out.println(socket.getRemoteSocketAddress() + "上线!"); } } static class ServerReadThread extends Thread { private Socket socket; public ServerReadThread(Socket socket) { this.socket = socket; } @Override public void run() { try { InputStream is = socket.getInputStream(); //4.把字节输入流包装成自己需要的流进行数据的读取。 BufferedReader br = new BufferedReader(new InputStreamReader(is)); //5.循环读取数据并打印到屏幕 String line; while ((line = br.readLine()) != null) { System.out.println("收到:" + line); } } catch (IOException e) { System.out.println(socket.getRemoteSocketAddress() + "下线!"); throw new RuntimeException(e); } } } }
客户端代码不变:
public class Client { public static void main(String[] args) throws Exception { System.out.println("==客户端的启动=="); // 1.创建一个Socket的通信管道,请求与服务端的端口连接。 Socket socket = new Socket("127.0.0.1", 8888); // 2.从Socket通信管道中得到一个字节输出流。 OutputStream os = socket.getOutputStream(); // 3.把字节流改装成自己需要的流进行数据的发送 PrintStream ps = new PrintStream(os); // 4.开始发送消息 Scanner sc = new Scanner(System.in); while (sc.hasNextLine()) { String msg = sc.nextLine(); ps.println(msg); ps.flush(); } } }
虽然解决了一些问题,但还有一些不完美
1.每个Socket接收到,都会创建一个线程,线程的竞争、切换上下文影响性能;
2.每个线程都会占用栈空间和CPU资源;
3.并不是每个socket都进行IO操作,无意义的线程处理;
4.客户端的并发访问增加时。服务端将呈现1:1的线程开销,访问量越大,系统将发生线程栈溢出,线程创建失
败,最终导致进程宕机或者僵死,从而不能对外提供服务