摘要:什么是线程在处理数据时,如果线程还处于将数据从读到的这段时间内,线程可以去做别的事情,等数据都读到了,线程再回来处理读到的数据是什么类比流的概念。
什么是NIO?
线程在处理数据时,如果线程还处于将数据从channel读到buffer的这段时间内,线程可以去做别的事情,等数据都读到buffer了,线程再回来处理读到的数据
channel是什么?类比流的概念。与流的区别在于
channel是可读可写的,但是一个流要么写要么读
chanel可以异步的读和写
数据总是从channel中读到buffer,或者从buffer中写到channel
流的读取或写一般是一次性的操作,数据在读取过程中不会有缓存,这也就意味着没有办法自己随便移动到想要读取的位置,要实现这个功能也就只能先缓存java中的channel有哪些?
FileChannel:连接文件的channel,通过文件对象的getChannel方法即可获取
FileChannel的write()方法不保证一次会写到channel中的字节数;另外它不能被设置为非阻塞,永远只能设置成阻塞模式
DatagramChannel:处理UDP协议连接,通过DatagramChannel.open()然后再获取socket执行绑定即可端口
SocketChannel:它是一个已经建立连接的TCP网络socket,用来处理TCP协议连接,通过SocketChannel.open()再调用自身的connet即可建立
ServerSocketChannel:用来监听TCP连接的建立,通过ServerSocketChannel.open()可以建立,随后就可以绑定需要监听的端口,并等待连接的到来,每个已建立的连接都会返回一个SocketChannel
非阻塞模式下,等待连接到来的accept方法会立马返回,注意判断SocketChannel是不是null;另外可能有多个连接建立,所以监听一般会放在一个while循环里面Buffer是什么?
用来方便操作内存块中数据的一个包装类。它有3个属性
capacity:表示Buffer能容纳的数据量,满了就不能再写
position:读或者写开始的位置
limit:写模式下表示能往buffer中写的数据量,最大值是capacity;读模式下表示能从buffer中获取的数据量,之前buffer中写了多少,就能读多少
从写模式转换到读模式需要用flip()完成,调用完成之后,limit会被设置成position当时的值,而positon会被设置成0;怎么读取数据到多个Buffer?读取数据完毕转换成写需要调用clear或者compact方法,其中clear会置position为0,limit为capacity,compact则会把原有的数据拷贝到开始的位置,然后其后的位置设置为position,limit则是capacity
mark和reset用法:在执行读取的时候,先mark住当前的位置,执行读取完成之后reset就回到原读取数据之前的位置了
创建一个数组用来放要写的数据,或者将要读到的数据,再执行读写操作即可,但是这种方式不适合读取变长消息
Buffer[] bArr = {head,body}; channel.read(bArr); //读 ,如果head本身会放自身容量的数据然后再往body中塞 Buffer[] wArr={head,body} channel.write(wArr);//写Selector是干啥的?
用来监控多个channel的事件,比如channel的连接建立、数据到达等等
实际上可以只用一个线程来管理所有的channelselector使用示例
//创建selector Selector selector = Selector.open(); //使用Selector必须设置为false,同时意味着FileChannel是不能用Selector channel.configureBlocking(false); // SelectionKey一共有4种值,分别代表4个事件:connect、accept、read、write // 通过方法 interestOps 可以得到注册时对channel感兴趣的事件,具体获取方式为 interestSet & SelectionKey.OP_ACCEPT 得到的结果即是否为ACCEPT事件 //通过这种方式即实现了注册,表明当前channel需要监听的是 read 事件,如果对多个事件感兴趣,那么可以使用 SelectionKey.OP_READ | SelectionKey.OP_WRITE 方式实现 //注册方法还可以添加另一个参数,attach,用来附加更多的信息给channel,比如将Buffer给channel SelectionKey key = channel.register(selector, SelectionKey.OP_READ); while(true) { //select()对channel注册的事件如果一个都没有好,那么阻塞住,返回值表示事件已经发生的chanel的个数; //selectNow()则不阻塞,没有准备好就返回0 int readyChannels = selector.select(); if(readyChannels == 0) continue; //用来获取准备好的channel SetselectedKeys = selector.selectedKeys(); Iterator keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if(key.isAcceptable()) { //SeverSocketChannel接受了一个新的连接 } else if (key.isConnectable()) { //和远程已经建立了连接 } else if (key.isReadable()) { //channel可读 } else if (key.isWritable()) { //channel可写 } //必须手动执行 keyIterator.remove(); } }
wakeup:如果channel当前刚好阻塞在select,会立马返回附
java NIO 参考
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71538.html
摘要:而我们现在都已经发布了,的都不知道,这有点说不过去了。而对一个的读写也会有响应的描述符,称为文件描述符,描述符就是一个数字,指向内核中的一个结构体文件路径,数据区等一些属性。 前言 只有光头才能变强 回顾前面: 给女朋友讲解什么是代理模式 包装模式就是这么简单啦 本来我预想是先来回顾一下传统的IO模式的,将传统的IO模式的相关类理清楚(因为IO的类很多)。 但是,发现在整理的过程已...
摘要:前言本篇主要讲解中的机制和网络通讯中处理高并发的分为两块第一块讲解多线程下的机制第二块讲解如何在机制下优化资源的浪费服务器单线程下的机制就不用我介绍了,不懂得可以去查阅下资料那么多线程下,如果进行套接字的使用呢我们使用最简单的服务器来帮助大 前言 本篇主要讲解Java中的IO机制和网络通讯中处理高并发的NIO 分为两块:第一块讲解多线程下的IO机制第二块讲解如何在IO机制下优化CPU资...
摘要:我想这很好的解释了中,仅仅一个都这么复杂,在单线程或者说串行的程序中,编程往往是很简单的,说白了就是调用,调用,调用然后返回。 Netty源码分析(三) 前提概要 这次停更很久了,原因是中途迷茫了一段时间,不过最近调整过来了。不过有点要说下,前几天和业内某个大佬聊天,收获很多,所以这篇博文和之前也会不太一样,我们会先从如果是我自己去实现这个功能需要怎么做开始,然后去看netty源码,与...
摘要:阻塞请求结果返回之前,当前线程被挂起。也就是说在异步中,不会对用户线程产生任何阻塞。当前线程在拿到此次请求结果的过程中,可以做其它事情。事实上,可以只用一个线程处理所有的通道。 准备知识 同步、异步、阻塞、非阻塞 同步和异步说的是服务端消息的通知机制,阻塞和非阻塞说的是客户端线程的状态。已客户端一次网络请求为例做简单说明: 同步同步是指一次请求没有得到结果之前就不返回。 异步请求不会...
摘要:的出现解决了这尴尬的问题,非阻塞模式下,通过,我们的线程只为已就绪的通道工作,不用盲目的重试了。注意要将注册到,首先需要将设置为非阻塞模式,否则会抛异常。 showImg(https://segmentfault.com/img/remote/1460000017053374); 背景知识 同步、异步、阻塞、非阻塞 首先,这几个概念非常容易搞混淆,但NIO中又有涉及,所以总结一下。 ...
阅读 1877·2021-11-25 09:43
阅读 2154·2021-11-19 09:40
阅读 3433·2021-11-18 13:12
阅读 1747·2021-09-29 09:35
阅读 670·2021-08-24 10:00
阅读 2516·2019-08-30 15:55
阅读 1719·2019-08-30 12:56
阅读 1825·2019-08-28 17:59