JavaIO进阶_NIO-NIO、核心API、Selector

目录

NIO

核心API

通道和流的区别

通道的重要实现类

Selector


为什么要用到NIO? 

适用于连接数目比较小且固定的场景,这种方式对服务器资源要求比较高,并发局限于应用中。

NIO

1.用于线程来轮询监控多个数据传输通道,哪个甬道准备好了(即有了一组可以处理的数据),就处理哪个通道

2.面向缓冲区的,非阻塞式的,基于选择器的

核心API

1.Channel 通道

2.Buffer 缓冲区

3.Selector 选择器


通道和流的区别

1.既可以从通道中读取数,又可以写数据到通道.但流的读写通常是单向的。

2.通道可以异步地读取。

3.通道中的数据总是先读到一个Buffer,或者总是要从一个Buffer中写入

通道的重要实现类

1.FileChannel 从文件中读取数据

2.DatagramChannel 通过UDP读写网络中的数据

3. Sockect 能通过TCP读写网络中的数据

4.ServerSocketChannel 可以监听新进来的TCP连接

package IO.nio;

import java.nio.IntBuffer;

public class BufferDemo {

    private static IntBuffer intBuffer;

    public static void main(String[] args) {

        //1.创建buffer
        intBuffer = IntBuffer.allocate(5);

        //2.向buffer传入数据
        for(int i=0 ; i<5 ;i++){
            intBuffer.put(i*2);
        }

        //3.读写切换
        intBuffer.flip();

        //4.buffer的读取
        while(intBuffer.hasRemaining()){
            System.out.println(intBuffer.get());
        }
    }
}
package IO.nio;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class ChannelDemo {

    public static void main(String[] args) throws IOException {

        String str = "hello";

        FileOutputStream fileOutputStream = new FileOutputStream("Test.txt");

        //文件数据的读写  ScoketChonnel 网络编程常用
        FileChannel fileChannel = fileOutputStream.getChannel();

        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        byteBuffer.put(str.getBytes());

        byteBuffer.flip();

        //写入数据
        fileChannel.write(byteBuffer);
        fileOutputStream.close();


    }
}

Selector

检测多个注册上来的通道中是否有事件发生,好处就是避免多行线程的情况下上下文的切换,导致的额外开销.

案例:

服务器:

package IO.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NIOServer {

    public static void main(String[] args) throws IOException {
        //1.创建ServerSocketChannel
        ServerSocketChannel serverSocketChannel =ServerSocketChannel.open();

        //2.创建select对象
        Selector selector = Selector.open();

        //3.绑定编口号 在服务器监听
        serverSocketChannel.socket().bind(new InetSocketAddress(6666));

        //4.非阻塞设置
        serverSocketChannel.configureBlocking(false);

        //5.绑定端口号,在服务器端监听
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while(true){
            if(selector.select(1000) == 0){
                System.out.println("服务器等待1秒,无连接");
            }

            Set<SelectionKey> selectionKeySet = selector.selectedKeys();

            Iterator<SelectionKey>keyIterator = selectionKeySet.iterator();

            while (keyIterator.hasNext()){
                SelectionKey key = keyIterator.next();

                //根据key对于的通道获取事件并作出处理
                if(key.isAcceptable()){
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);//非阻塞设置
                    socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024));

                }

                if(key.isReadable()){
                    SocketChannel channel = (SocketChannel) key.channel();
                    ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
                    channel.read(byteBuffer);
                    System.out.println("from客户端"+new String(byteBuffer.array()));
                }
                //手动溢出当前SelectionKey,防止多线程情况下的重复操作
                keyIterator.remove();
            }
        }

    }
}

客户端:

package IO.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class NIOClient {
    public static void main(String[] args) throws IOException {


        SocketChannel socketChannel = SocketChannel.open();

        socketChannel.configureBlocking(false);

        InetSocketAddress inetSocketAddress = new InetSocketAddress(6666);

        if(!socketChannel.connect(inetSocketAddress)){

            while(!socketChannel.finishConnect()){
                System.out.println("等待连接");
            }
        }

        String str = "hello";
        ByteBuffer buffer = ByteBuffer.wrap(str.getBytes());

        //发送数据
        socketChannel.write(buffer);
        System.in.read();

    }
}

 先开启服务器,接着开启客户端连接,就可以观察到:

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

什么时候养猫猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值