NIO案例详解

本文介绍了NIO(非阻塞I/O)的概念,对比了它与BIO的区别,并通过一个时间服务器的例子详细阐述了NIO的工作流程,包括客户端与服务端的交互,以及Selector在多客户端请求处理中的作用。
摘要由CSDN通过智能技术生成

一、

NIO解释:NIO官方的解释是NEW I/O,意思是相对与BIO(同步阻塞I/O)来说是全新的,但是大部分人更喜欢叫他no-block I/O(同步非阻塞I/O),因为他相对于BIO的最大改变就是非阻塞的,我们知道传统的Socket下的流都是阻塞I/O,也就是客户端的一个请求对应服务端的一个线程,并且这个线程是一直阻塞的直到请求结束,对于线程这种宝贵的资源来说,如果并发量太大同时处理线程又阻塞时,那么势必会导致服务端资源耗尽,拖垮整个系统,就算我们用线程池代替传统的手动创建线程(这样避免了频繁的新建、销毁线程,因为线程创建也是消耗资源的,达到重复利用线程的目的,同时通过线程池也能控制客户端的并发数)但是这并没有解决一个请求对应一个线程的问题,所提他本质上还是BIO,此时NIO便产生了,NIO的最大改变就是改变了一请求一线程的状况,只要只要一个Selector就可以监听注册到其上的所有Channel,通过轮询准备好的Channel实现单线程处理多客户端请求;

接下来我们通过一个例子来看看BIO:这个例子就是一个client像server发送一个请求,server像client端返回当前时间;

TimeServer:

package com.ck.prefix.nio;

import java.io.IOException;

public class TimeServer {

    public static void main(String[] args) throws IOException {
        MultiplexerTimeServer m = new MultiplexerTimeServer(8081);
        //起一个单独的线程来处理来自客户端的请求
        new Thread(m,"NIO-MultiplexerTimeServer").start();
    }
}
 

MultiplexerTimeServer:

package com.ck.prefix.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

public class MultiplexerTimeServer implements Runnable {
   //多路复用选择器
    private Selector selector;
    private ServerSocketChannel serverChannel;
    private volatile boolean isStop;


    /**
     * 初始化多路复用器,绑定接口
     *
     * @param port
     * @throws IOException
     */
    public MultiplexerTimeServer(int port) throws IOException {
        //初始化多路复用器
        selector = Selector.open();
        //初始化ServerChannel
        serverChannel = ServerSocketChannel.open();
        //设置为未阻塞模式
        serverChannel.configureBlocking(false);
        //绑定ip、port,设置backlog
        serverChannel.socket().bind(new InetSocketAddress("127.0.0.1", port), 1024);
        //1、将serverChannel注册到selector上,并监听accept事件(就是客户端的connect请求)
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("server初始化完成");
    }

    public void run() {
        //服务端单线程一直循环监听来自客户端的请求
        while (!isStop) {
            try {
                //延迟1s,不管有没有客户端请求都阻塞1s然后往下执行,如果不设置那么会一直阻塞直到有客户端的请求过来
                selector.select(1000);
                //循环取SelectionKey
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectionKeys.iterator();
                SelectionKey key = null;
                while (it.hasNext()) {
                    k
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值