关于阻塞与非阻塞:https://www.cnblogs.com/jhxxb/p/11272727.html

 

一、传统的 IO 流都是阻塞式的

Java NIO Selector

当一个线程调用 read() 或 write() 时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务。

因此,在网络通信进行 IO 操作时,由于线程会阻塞,所以服务器端必须为每个客户端都提供一个独立的线程进行处理,当服务器端需要处理大量客户端时,性能急剧下降。

Java NIO Selector
package nio;

import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Scanner;


public class TestBlockingNIO {

    // 客户端
    @Test
    public void client() throws IOException {
        // 获取通道
        SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));

        // 分配指定大小的缓冲区
        ByteBuffer buf = ByteBuffer.allocate(1024);

        // 发送到服务端
        Scanner scan = new Scanner(System.in);
        while (scan.hasNext()) {
            String str = scan.next();
            buf.put(str.getBytes());
            buf.flip();
            sChannel.write(buf);
            buf.clear();

            if ("exit".equals(str)) {
                break;
            }
        }


        // 接收服务端的反馈
        sChannel.shutdownOutput();
        int len = 0;
        while ((len = sChannel.read(buf)) != -1) {
            buf.flip();
            System.out.println(new String(buf.array(), 0, len));
            buf.clear();
        }

        // 关闭通道
        sChannel.close();
    }

    // 服务端
    @Test
    public void server() throws IOException {
        // 获取通道
        ServerSocketChannel ssChannel = ServerSocketChannel.open();

        // 绑定连接
        ssChannel.bind(new InetSocketAddress(9898));

        retry:
        while (true) {
            // 获取客户端连接的通道
            SocketChannel sChannel = ssChannel.accept();

            // 分配指定大小的缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);

            // 接收客户端的数据
            while (sChannel.read(buf) != -1) {
                String str = new String(buf.array()).trim();
                if ("exit".equals(str)) {
                    break retry;
                }
                buf.flip();
                System.out.println(str);
                buf.clear();
            }

            // 发送反馈给客户端
            buf.put("服务端接收数据成功!".getBytes());
            buf.flip();
            sChannel.write(buf);

            // 关闭通道
            sChannel.close();
        }

        // 关闭通道
        ssChannel.close();
    }
}
View Code

相关文章: