我们知道传统BIO模型在等待客户端连接时是阻塞的,读取数据时如果没有数据,也是阻塞的,而NIO则可以配置成非阻塞,废话不多说,直接看代码:
- import java.net.InetSocketAddress;
- import java.nio.ByteBuffer;
- import java.nio.channels.ServerSocketChannel;
- import java.nio.channels.SocketChannel;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.concurrent.TimeUnit;
-
- public class NioServer {
- public static void main(String[] args) throws Exception {
- ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
- //服务端非阻塞
- serverSocketChannel.configureBlocking(false);
- serverSocketChannel.bind(new InetSocketAddress(8888));
- List
clients = new LinkedList<>(); - while (true) {
- TimeUnit.SECONDS.sleep(1);
- SocketChannel client = serverSocketChannel.accept();
- if (null == client) {
- System.err.println("没有新的客户端连接.....");
- } else {
- //客户端非阻塞
- client.configureBlocking(false);
- System.err.println(client.socket());
- clients.add(client);
- }
- ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
- for (SocketChannel socketChannel : clients) {
- int num = socketChannel.read(byteBuffer);
- if (num > 0) {
- byteBuffer.flip();
- byte[] bytes = new byte[byteBuffer.limit()];
- byteBuffer.get(bytes);
- String b = new String(bytes);
- System.err.println(b);
- byteBuffer.clear();
- }
- }
- }
- }
- }
//服务端非阻塞 serverSocketChannel.configureBlocking(false); //客户端非阻塞 client.configureBlocking(false);
这两行代码非常重要,serverSocketChannel.configureBlocking(false)这里设置的是true,那么只要没有客户端连接,SocketChannel client = serverSocketChannel.accept();这一行就会阻塞住,就不会每隔一秒打印没"有新的客户端连接....."
直到通过telnet连接一个客户端之后:
但是还是会继续阻塞等待下一个客户端连接,我们把serverSocketChannel.configureBlocking(false)这一行还原成false,client.configureBlocking(false);设置为true,再看效果:
第一个客户端连接上之后,一定要输入数据,不然read就会一直阻塞
我们再把两个选项都回复到false,然后丢到linux系统去运行,看看系统调用的情况(如何查看系统调用情况,之前有一篇BIO模型的文章Java当中的BIO模型-CSDN博客):

可以看到accept并不会像NIO一样阻塞,而是直接返回-1,write(2, "\346\262\241\346\234\211\346\226\260\347\232\204\345\256\242\346\210\267\347\253\257\350\277\236\346\216\245.....", 32) = 32
这一行其实就是输出“有新的客户端连接.....”这句话