栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java NIO初体验 简述加小项目体验

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java NIO初体验 简述加小项目体验

NIO 非阻塞 IO 1介绍 1.1 JAVA NIO

BIO:阻塞式IO,我们传统的流式IO就是阻塞式IO,意思式在读写的过程中可能发生阻塞
NIO:非阻塞IO,读写过程中不会产生阻塞。
AIO:在NIO基础上完成异步非阻塞。 NIO属于同步非阻塞。
同步:单线程上执行的操作,执行存在先后顺序。
异步:多个线程执行的操作,执行没有先后顺序。
IO发生阻塞最常见的场景出现与网络上的IO操作。好比TCP连接中Socket产生IO阻塞。
之前使用流式IO完成TCP通讯式,只能依靠多线程来完成同时多客户端交互。
那么使用了NIO后,就可以以单线程形式完成上述操作。
好处:资源开销小,运行性能好。
缺点:NIO设计不够优雅。以后有了NIO知识后,可以学习netty框架。

NIO实现(复制文件)代码演示:

public class NIODemo {
    public static void main(String[] args) throws IOException {
        
        FileInputStream fis = new FileInputStream("NARUTO.JPG");
        FileOutputStream fos = new FileOutputStream("NARUTO_CP.JPG");
        //通过流获取对应的NIO通道,用通道对文件进行读写操作
        FileChannel inChannel = fis.getChannel();
        FileChannel outChannel = fos.getChannel();
        
        //创建一个10KB的缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024*10);

        int len;//记录每次实际读取到的字节数
        while((len = inChannel.read(buffer))!=-1) {
            buffer.flip();
            outChannel.write(buffer);
            buffer.clear();
        }

        System.out.println("复制完毕");
        inChannel.close();
        outChannel.close(); 
    }
}
1.2 NIO缓存操作

​ 读入数据装满空间 读入空间的一部分数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SQVWPDgB-1656237914892)(C:UserstarenaAppDataRoamingTyporatypora-user-imagesimage-20220626163953324.png)]

小项目体验IO与NIO区别:

服务端代码:

public class NIOServer {
    //存放所有客户端Channel,便于广播消息
    private List allChannel = new ArrayList<>();

    public void start(){
        try {
            
            ServerSocketChannel serverSocketChannel
                                = ServerSocketChannel.open();
            //需要显示的设置为非阻塞状态,必须为非阻塞状态才能交给多路选择器监控事件
            serverSocketChannel.configureBlocking(false);
            //打开服务端口8088,客户端就可以通过8088端口进行连接了
            serverSocketChannel.bind(new InetSocketAddress(8088));
            
            //创建一个多路选择器
            Selector selector = Selector.open();


            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            
            while(true) {
                System.out.println("主线程等待多路选择提示是否有事件要处理...");
                selector.select();//该方法会形成阻塞
                System.out.println("多路选择器监听到有事件要进行处理!!");
                //通过多路选择器将所有待处理的事件全部获取回来进行逐一处理
                Set set = selector.selectedKeys();
                //遍历每一个事件并进行对应处理
                for (SelectionKey key : set) {
                    //使用分支判断该事件是什么事件,以便做对应的处理
                    //判断该事件是否为ServerSocketChannel中的accept事件(有客户端连接了)
                    if (key.isAcceptable()) {
                        //通过事件获取相关通道来进行对应的操作
                        //对于accept事件而言,只有ServerSocketChannel会触发。
                        ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                    
                        SocketChannel socket = ssc.accept();//接电话
                    
                        if (socket != null) {
                            //将当前SocketChannel存入共享集合
                            allChannel.add(socket);

                            //将该SocketChannel注册到多路选择上,让其监听发送消息过来的事件
                            socket.configureBlocking(false);//将SocketChannel设置为非阻塞的,这样才能交给多路选择器
                            socket.register(selector, SelectionKey.OP_READ);
                        }
                    //判断事件是否为有的通道上有消息可以读取(某个客户端发送消息过来了)
                    }else if(key.isReadable()){
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024*10);
                        int len = socketChannel.read(buffer);
                        if(len==-1){//客户端断开连接,服务端这里才会读取到-1
                            socketChannel.close();//断开连接
                            allChannel.remove(socketChannel);
                        }
                        buffer.flip();//position-limit之间就是刚刚读取到的数据了。
                        
                        byte[] data = new byte[buffer.limit()];
                        
                        buffer.get(data);//调用后data中保存的就是position-limit之间的数据
                        
                        String line = new String(data, StandardCharsets.UTF_8);
                        System.out.println("客户端说:"+line);

                        //遍历allChannel集合,将消息发送给所有客户端
                        for(SocketChannel sc : allChannel){
                            buffer.flip();//limit=position,position=0
                            sc.write(buffer);//limit与position值相同了
                        }

                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        NIOServer server = new NIOServer();
        server.start();
    }
}

客户端代码:

public class Client {
    
    private Socket socket;
    
    public Client(){
        try {
            
            System.out.println("正在连接服务端...");
            socket = new Socket("localhost",8088);
            System.out.println("已连接服务端!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void start(){
        try {
            ServerHandler serverHandler = new ServerHandler();
            Thread t = new Thread(serverHandler);
            t.setDaemon(true);
            t.start();
            
            //低级流,通过该流写出的字节就发送给了远端计算机
            OutputStream out = socket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            BufferedWriter bw = new BufferedWriter(osw);
            PrintWriter pw = new PrintWriter(bw,true);

            Scanner scanner = new Scanner(System.in);
            while(true){
                String line = scanner.nextLine();//获取控制台输入的一行字符串
                if("exit".equalsIgnoreCase(line)){
                    break;//停止循环
                }
                pw.println(line);//将输入的内容发送给服务端
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //与服务端断开连接
            try {
                
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Client client = new Client();
        client.start();
    }

    private class ServerHandler implements Runnable{
        public void run() {
            try{
                  
                InputStream in = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(isr);

                String message;
                while((message = br.readLine()) != null){
                    System.out.println(message);
                }
            }catch(IOException e){

            }
        }
    }
}
                BufferedReader br = new BufferedReader(isr);

                String message;
                while((message = br.readLine()) != null){
                    System.out.println(message);
                }
            }catch(IOException e){

            }
        }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/996646.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号