When encountering concurrent service scenarios, we can take the following measures:
Synchronous block IO implementation
public class DemoServer extends Thread { private ServerSocket serverSocket; public int getPort() { return serverSocket.getLocalPort(); } public void run() { try { serverSocket = new ServerSocket(0); Socket Socket = serversocket.accept (); Socket = serversocket.accept (); RequesHandler requesHandler = new RequesHandler(socket); requesHandler.start(); } } catch (IOException e) { e.printStackTrace(); } finally { if (serverSocket ! = null) { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); }; } } } public static void main(String[] args) throws IOException { DemoServer server = new DemoServer(); server.start(); try (Socket client = new Socket(InetAddress.getLocalHost(), server.getPort())) { BufferedReader buferedReader = new BufferedReader(new InputStreamReader(client.getInputStream())); buferedReader.lines().forEach(s -> System.out.println(s)); Class RequesHandler extends Thread {private Socket Socket; RequesHandler(Socket socket) { this.socket = socket; } @Override public void run() { try (PrintWriter out = new PrintWriter(socket.getOutputStream());) { out.println("Hello world!" ); out.flush(); } catch (Exception e) { e.printStackTrace(); }}}Copy the code
Each thread has a separate thread structure, which takes up a lot of memory resources. It is not reasonable to enable one thread per client, so it can be optimized by thread pooling.
// When a new client connects, the request Socket is wrapped into a task and placed in the thread pool for execution. serverSocket = new ServerSocket(0); executor = Executors.newFixedThreadPool(8); while (true) { Socket socket = serverSocket.accept(); RequesHandler requesHandler = new RequesHandler(socket); executor.execute(requesHandler); }Copy the code
NIO implementation
NIO (non-blocking IO) multiplexing mechanism
public class NIOServer extends Thread { public void run() { try (Selector selector = Selector.open(); ServerSocketChannel serverSocket = ServerSocketChannel.open();) {// Create Selector and Channel serversocket.bind (new InetSocketAddress(inetaddress.getLocalhost (), 8888)); serverSocket.configureBlocking(false); Serversocket. register(Selector, selectionkey.op_accept); while (true) { selector.select(); Set<SelectionKey> selectedKeys = selectedKeys(); Iterator<SelectionKey> iter = selectedKeys.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); SayHelloWorld ((ServerSocketChannel) key.channel())); iter.remove(); } } } catch (IOException e) { e.printStackTrace(); } } private void sayHelloWorld(ServerSocketChannel server) throws IOException { try (SocketChannel client = server.accept();) { ByteBuffer readBuffer = ByteBuffer.allocate(32); client.read(readBuffer); System.out.println("Server received : " + new String(readBuffer.array())); ByteBuffer writeBuffer = ByteBuffer.allocate(128); writeBuffer.put("hello xiaoming".getBytes()); writeBuffer.flip(); client.write(writeBuffer); //client.write(Charset.defaultCharset().encode("Hello world!" )); } } public static void main(String[] args) throws IOException { NIOServer server = new NIOServer(); server.start(); try { SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress(InetAddress.getLocalHost(), 8888)); ByteBuffer writeBuffer = ByteBuffer.allocate(32); ByteBuffer readBuffer = ByteBuffer.allocate(32); writeBuffer.put("hello".getBytes()); writeBuffer.flip(); while (true) { writeBuffer.rewind(); socketChannel.write(writeBuffer); // readBuffer.clear(); socketChannel.read(readBuffer); System.out.println("Client received : " + new String(readBuffer.array())); } } catch (IOException e) { } } /** * @return */ private int getPort() { return 8888; }Copy the code
Third, summary
In the previous two examples, blocking IO and pseudo asynchronous IO, one using new threads and the other using thread pool management, both are synchronous blocking mode, so multithreading is required to achieve multitasking.
NIO uses the single-thread polling event mechanism to efficiently locate ready channels to decide what to do. Only the SELECT phase is blocked, which can effectively avoid the problem of frequent thread switching when a large number of clients are connected, and the scalability of the application has been greatly improved.