Java NIO 基础

Java NIO 基础

  • 1. NIO 介绍
  • 2. NIO 三大组件
    • 2.1 Channel
      • 2.1.1 常见的 Channel
      • 2.1.2 常用方法
    • 2.2 Buffer
      • 2.2.1 常见的 Buffer
      • 2.2.2 重要属性
      • 2.2.3 常用方法
    • 2.3 Selector
      • 2.3.1 四种事件类型

1. NIO 介绍

NIO(non-blocking io):非阻塞IO,JDK1.4 引入。

2. NIO 三大组件

2.1 Channel

Channer是读写数据的双向通道,类似于传统IO中的Stream,但是Stream只能单向操作。如:InputStream只能读操作,OutputStream只能写操作。

2.1.1 常见的 Channel

  • FileChannel:文件IO通道,用于文件的读写
  • DatagramChannel:UDP协议数据报通信
  • SocketChannel:网络套接字IO通道,TCP协议客户端
  • ServerSocketChannel:网络套接字IO通道,TCP协议服务端

2.1.2 常用方法

  • read(ByteBuffer buffer):从Channel中读取到ByteBuffer中,如果Channel中没有数据会一直堵塞到可读
  • read(ByteBuffer buffer,Long timeout):从Channel中读取到ByteBuffer中,超过时间会报错
  • write(ByteBuffer buffer):将数据写到Channel中,如果Channel中没有可写空间会一直堵塞到可写
  • write(ByteBuffer buffer, Long timeout):将数据写到Channel中,超过时间会报错
  • flush():将Channel中缓冲区数据刷到底层设备
  • register(Selector selector, SelectionKey key):将Channel注册到Selector
  • configureBlocking(boolean b):设置Channel是否为阻塞模式
  • socket():获取底层的Socket对象
  • isConnected():Channel是否已经连接上
  • isReadable():Channel是否可读
  • isWriteable():Channel是否可写
  • getRemoteAddress():Channel对应的远程地址
  • getLocalAddress():Channel对应的本地地址
  • open():Channel是否打开

2.2 Buffer

Buffer:缓冲读写数据,每一个Buffer对象关联一个字节数组。
在这里插入图片描述

2.2.1 常见的 Buffer

  • ByteBuffer
  • CharBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

2.2.2 重要属性

  • capacity:Buffer所占的内存大小,设置后不能修改
  • limit:Buffer中可以操作的数据大小
  • position:下一个要读/写的数据索引
  • mark:标记当前position的位置,可以通过reset()position恢复到mark位置

2.2.3 常用方法

  • capacity():返回capacity的值
  • limit():返回limit的值
  • limit(int n):设置limit的值
  • position():返回position的值
  • position(int n): 设置position的值
  • mark():对Buffer做标记
  • reset():把position恢复到mark位置
  • rewind():设置position为0,取消mark标记
  • hasRemaining():判断Buffer中是否有元素
  • get():从Buffer中读取一个字节
  • get(byte[] b):从Buffer中读取多个字节
  • get(int index):从Buffer中读取指定索引位的字节
  • put(byte b):往Buffer中存一个字节
  • put(byte[] b):往Buffer中存多个字节
  • put(int index, byte b):往Buffer指定索引位存字节
  • clear():清空Buffer
  • compact():清空position之前的字节
  • flip():将limit设置为position的值,position设置为0

2.3 Selector

Selector配合一个线程管理多个Channel,获取Channel上发生的事件

2.3.1 四种事件类型

  • OP_CONNECT:连接成功后(只客户端使用)
  • OP_ACCEPT:客户端请求连接时(只服务端使用)
  • OP_READ:读缓冲区有可读数据时
  • OP_WRITE:写缓冲区有可写空间时
    在这里插入图片描述
package com.learn.wesay;

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.nio.charset.StandardCharsets;
import java.util.Iterator;

public class Server {
    public static void main(String[] args) throws IOException {
        // 创建Selector管理多个Channel
        Selector selector = Selector.open();

        // 创建服务端套接字通道
        ServerSocketChannel server = ServerSocketChannel.open();
        // 设置为非阻塞
        server.configureBlocking(false);
        // 绑定端口
        server.bind(new InetSocketAddress(8888));

        // Channel注册到Selector,只处理accept事件
        server.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            // 没有事件发生线程阻塞,有事件线程才会恢复运行
            selector.select();
            // 所有发生的事件
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                if (selectionKey.isAcceptable()) {
                    handlerAccept(selectionKey, selector);
                }

                if (selectionKey.isReadable()) {
                    handlerRead(selectionKey, selector);
                }

                iterator.remove();
            }
        }

    }

    private static void handlerAccept(SelectionKey selectionKey, Selector selector) {
        ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel();
        try {
            SocketChannel channel = server.accept();
            channel.configureBlocking(false);
            channel.register(selector, SelectionKey.OP_READ);
            System.out.println(channel);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static void handlerRead(SelectionKey selectionKey, Selector selector) {
        SocketChannel channel = (SocketChannel) selectionKey.channel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        try {
            int read = channel.read(byteBuffer);
            if (read == -1) {
                // 客户端socket正常断开
                selectionKey.cancel();
            } else {
                byteBuffer.flip();
                System.out.println(StandardCharsets.UTF_8.decode(byteBuffer));
            }
        } catch (IOException e) {
            // 客户端socket异常断开
            selectionKey.cancel();
        }
    }
}

public class Client {
    public static void main(String[] args) throws IOException {
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress("localhost", 8888));
        socketChannel.write(Charset.defaultCharset().encode("你好"));
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/633078.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无网环境禁止 WPS 提示登录,且基本功能按钮可用

目前 WPS 升级后&#xff0c;每次打开都会提示你登录 WPS&#xff0c;并且在未登录之前所有基本功能按钮是置灰状态&#xff0c;无法使用。 如此一来&#xff0c;在内网或无网环境&#xff0c;我们无法登陆 WPS &#xff0c;就给我们的使用带来了极大的不便&#xff0c;那么有没…

go升级后 编译的exe在win7上无法正常运行

D:/Go/src/runtime/sys_windows_amd64.s:65 x75 fpx22fca sp-0x22fc8日 升级到go 1.21后报一堆错误&#xff0c;要死了啊 原来是go 1.21不支持win7了&#xff0c;必须把go退回到1.20版本 谷歌发布编程语言 Go 1.21 版本&#xff1a;取消支持微软 Win7/8 及苹果 macOS 10.13/10…

Vue3实战笔记(33)—组件传值props终章

文章目录 前言一、运行时声明、基于类型的声明二、一个小小的好奇心三、非 script setup场景下总结 前言 在 Vue 3 中&#xff0c;组件的声明方式主要有两种&#xff1a;运行时声明和基于类型的声明。这两种方式在 Vue 3 的 Composition API 中体现得尤为明显。 一、运行时声明…

如何使用Docker快速运行Firefox并实现远程访问本地火狐浏览器

文章目录 1. 部署Firefox2. 本地访问Firefox3. Linux安装Cpolar4. 配置Firefox公网地址5. 远程访问Firefox6. 固定Firefox公网地址7. 固定地址访问Firefox Firefox是一款免费开源的网页浏览器&#xff0c;由Mozilla基金会开发和维护。它是第一个成功挑战微软Internet Explorer浏…

基于manifest文件批量将coding的仓库导入gitlab中

文章目录 写在前面的话背景编写manifest文件最终效果 写在前面的话 前面有讲过通过manifest清单导入项目到gitlab中&#xff0c;但是实际的操作是不同gitlab实例之间的操作&#xff0c;然而对于在不同gitlab实例的repo迁移而言&#xff0c;显然direct transfer会更合适。 背景…

Spring6笔记(五):国际化、数据校验、提前编译

九、国际化&#xff1a;i18n 9.1 i18n概述 9.2 Java国际化 9.3 Spring6国际化 十、数据校验&#xff1a;Validation 10.1 Spring Validation 概述 10.2 实验一&#xff1a;通过 validator 接口实现 10.3 实验三&#xff1a;Bean Validation 注解 10.4 实验四&#xff1a;实现…

深入了解 RabbitMQ:构建可靠消息传递系统的关键

前言 在现代分布式应用程序开发中&#xff0c;构建可靠的消息传递系统至关重要。RabbitMQ 作为一款强大的消息代理软件&#xff0c;为开发人员提供了丰富的工具和解决方案。本文将深入探讨 RabbitMQ 的核心概念、工作原理以及其在实际应用中的应用场景。 一、什么是 RabbitMQ…

[力扣]——231.2的幂

题目描述&#xff1a; 给你一个整数 n&#xff0c;请你判断该整数是否是 2 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 如果存在一个整数 x 使得 n 2x &#xff0c;则认为 n 是 2 的幂次方。 bool isPowerOfTwo(int n){ if(n0)retur…

Diffusion Policy:基于扩散模型的机器人动作生成策略

项目地址&#xff1a; Diffusion Policy (columbia.edu) 一、摘要 本文介绍了 "扩散策略"&#xff0c;这是一种生成机器人行为的新方法&#xff0c;它将机器人的视觉运动策略&#xff08;visuomotor policy&#xff09;表示为条件去噪扩散过程&#xff08;conditi…

15:00面试,15:08出来,面试问的有点变态。。。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天…

Manjaro /opt/google/chrome error

mingcai Manjaro in /opt/google/chrome [22:34:02] $ ./google-chrome [62841:62841:0516/223407.119870:ERROR:process_singleton_posix.cc(353)] 其他计算机 (mingcai-systemproductname) 的另一个 Google Chrome 进程 (2931) 好像正在使用此个人资料。Chrome 已锁定此个人…

PySide6 QStateMachine状态机的实现

PySide6的状态机模块提供了一种方便的方式来实现状态机模式&#xff0c;用于管理程序的状态和状态转换。通过使用PySide6的状态机模块&#xff0c;开发者可以更加清晰地组织程序逻辑&#xff0c;使程序更易于维护和扩展。 在PySide6中&#xff0c;状态机相关的类主要包括&…

探索k8s集群中kubectl的陈述式资源管理

一、k8s集群资源管理方式分类 1.1陈述式资源管理方式&#xff1a;增删查比较方便&#xff0c;但是改非常不方便 使用一条kubectl命令和参数选项来实现资源对象管理操作 即通过命令的方式来实 1.2声明式资源管理方式&#xff1a;yaml文件管理 使用yaml配置文件或者json配置文…

Monkey自动化测试(Android)吐血整理(超详细)

一、前言 随机的命令对APP进行自动化测试&#xff0c;可以快速发现APP的问题&#xff0c;若执行时设置的-S 100出现了一个错误&#xff0c;后面再执行时&#xff0c;只需设置相同的-S&#xff0c;就会按照第一次执行命令的顺序再次执行 自动化就是比较有针对性的对某一个功能…

Jenkins部署成功后自动发通知到钉钉群

钉钉上如何配置 选择钉钉群&#xff0c;找到群设置-机器人-添加机器人 选择自定义 选择【添加】 选择【加签】&#xff0c;复制值&#xff0c;后续在jenkins里配置时会用到 复制Webhook地址&#xff0c;后面在jenkins里配置的时候要用到 Jenkins上如何配置 系统管理-插件管…

数学建模~~多目标规划

1.认识多目标规划 &#xff08;1&#xff09;前面我们介绍的是单目标规划&#xff0c;现在我们要认识一下多目标规划&#xff1a; &#xff08;2&#xff09;使用上面的这个题目作为例子&#xff0c;简单的翻译一下题干&#xff0c;这个题目说的就是 有1&#xff0c;2这两种产…

LeetCode题练习与总结:二叉树的最大深度--104

一、题目描述 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;root […

Nginx/阿里云/二级域名的配置和使用

阿里云域名解析配置如下&#xff1a; nginx配置如下&#xff1a; 访问地址&#xff1a; zhadmin.iotzzh.com image.png

SD-WAN EVPN基本原理

SD-WAN EVPN是一种用于Overlay业务网络和底层传输网络分离以及业务网络路由和传输网络路由分离的VPN技术。SD-WAN EVPN技术采用类似于BGP/MPLS IP VPN的机制&#xff0c;通过扩展BGP协议&#xff0c;使用扩展后的可达性信息&#xff0c;使不同站点的底层传输网络互通&#xff0…

【NumPy】关于numpy.loadtxt()函数,看这一篇文章就够了

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…