java非阻塞NIO和阻塞IO
1 非阻塞NIO和阻塞IO
1.1 定义
阻塞IO:线程被阻塞,去处理一个读取和写入,中间如果有等待时间,则线程被占用,也不能处理其他任务;
非阻塞IO(new IO):引入了通道的概念,一个连接对应一个通道,为每个通道配置缓冲区,线程去轮询查看的通道的状态,如果某个通道上有数据准备好了,则通道状态会发生改变,线程就去处理这个读写操作;
1.2 非阻塞实现的核心Selector
Selector 一般称为选择器 ,或者多路复用器。在通道上建立socket连接,然后调用channel.register(selector, Selectionkey.OP_READ);将通道注册到Selector上,并且申明这个连接是读(READ)、写(WRITE)、接受(ACCEPT)、连接( CONNECT),或者四个功能都包括;这样就可以用一个线程,一个Selector去管理多个连接;selector会去循环查询各个通道的状态,如果通道状态发生改变,会去判断通道的类型(读、写、接受、连接),然后再对应去做处理;
(1)Selector的创建
通过调用Selector.open()方法创建一个Selector对象,如下:
Selector selector = Selector.open();
(2)注册Channel到Selector
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, Selectionkey.OP_READ);
第二个参数是通道的类型,有四个值,方便位运算;
读 : SelectionKey.OP_READ ( 1)
写 : SelectionKey.OP_WRITE ( 4)
连接 : SelectionKey.OP_CONNECT ( 8)
接收 : SelectionKey.OP_ACCEPT ( 16)
若注册时不止监听一个事件,则可以使用“位或”操作符连接。
1.3 SelectableChannle通道上建立连接
(1)非阻塞通道
AbstractSelectableChannel抽象类继承了SelectableChannle接口, SocketChannel、ServerSocketChannel、DatagramChannel都是直接继承了 AbstractSelectableChannel抽象类 。SocketChannel是用于socket客户端,ServerSocketChannel是用于socket服务器;
(2)阻塞通道
FileChannel还是不能实现非阻塞,对文件的读写IO,不能同时写入一个文件。
1.4 SelectionKey通道状态
SelectionKey 代表各个通道的状态信号,通过调用选择器的函数来获取到所有有信号的通道的状态,Set<SelectionKey> keys = selector.selectedKeys();然后在通过SelectionKey的方法去判断是哪种信号。
(1)key.attachment(); //返回SelectionKey的attachment,attachment可以在注册channel的时候指定。
(2)key.channel(); // 返回该SelectionKey对应的channel。
(3)key.selector(); // 返回该SelectionKey对应的Selector。
(4)key.interestOps(); //返回代表需要Selector监控的IO操作的bit mask
我们可以通过与操作来判断Selector是否对Channel的某种事件感兴趣,感兴趣的boolean为1;
int interestSet = selectionKey.interestOps();
boolean isInterestedInAccept = (interestSet & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT;
boolean isInterestedInConnect = interestSet & SelectionKey.OP_CONNECT;
boolean isInterestedInRead = interestSet & SelectionKey.OP_READ;
boolean isInterestedInWrite = interestSet & SelectionKey.OP_WRITE;
(5)key.readyOps(); // 返回一个bit mask,代表在相应channel上可以进行的IO操作。可以通过与运算去判断是否准备好;
(6)直接调用SelectionKey对象的函数判断信号状态
boolean isReadable() 检测 Channal 中读事件是否就绪
boolean isWritable() 检测 Channal 中写事件是否就绪
boolean isConnectable() 检测 Channel 中连接是否就绪
boolean isAcceptable() 检测 Channel 中接收是否就绪
1.5 阻塞IO使用实例
客户端向服务器端发送一张图片
package com.happybks.nio.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
importjava.nio.file.Paths;
importjava.nio.file.StandardOpenOption;
import org.junit.Test;
publicclass TestBlockingNIO{
//客户端
@Test
public void client() throws IOException{
//1、获取通道(open这种方法是jdk1.7之后才引入的)
SocketChannel socketChannel = SocketChannel.open(newInetSocketAddress("127.0.0.1",8888));
//2、分配指定大小的缓冲区
ByteBuffer buf=ByteBuffer.allocate(1024);
//3、从本地读取文件,并发送到服务端
FileChannel inFileChannel=FileChannel.open(Paths.get("D:/Test/NIO/1.jpg"),StandardOpenOption.READ);
while(inFileChannel.read(buf)!=-1){
buf.flip();
socketChannel.write(buf);
buf.clear();
}
//在阻塞IO下,如果关闭socketChannel,那么服务端不知道客户端是否已经把所有数据发完,所以会一直阻塞。
socketChannel.shutdownOutput();
//另一种方法就是把这个线程切换成非阻塞模式
//接收服务端反馈
intlen =0;
while((len = socketChannel.read(buf)) !=-1){
buf.flip();
System.out.println(newString(buf.array(),0,len));
}
//4、关闭通道
inFileChannel.close();
socketChannel.close();
}
//服务端
@Test
public void server() throws IOException{
//1、获取端口
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//2、绑定连接
serverSocketChannel.bind(newInetSocketAddress(8888));
//3、获取客户端连接的通道
SocketChannel socketChannel = serverSocketChannel.accept();
//4、接收客户端的数据,保存到本地。(提到本地,就要弄个FileChannel)
FileChannel outFileChannel = FileChannel.open(Paths.get("D:/Test/NIO/2.jpg"),StandardOpenOption.WRITE,StandardOpenOption.CREATE);
ByteBuffer buf=ByteBuffer.allocate(1024);
while(socketChannel.read(buf)!=-1){
buf.flip();
outFileChannel.write(buf);
buf.clear();
}
//发送反馈给客户端
buf.put("服务端接收数据成功!".getBytes());
buf.flip();
socketChannel.write(buf);
socketChannel.close();
outFileChannel.close();
serverSocketChannel.close();
}
}
1.6 非阻塞IO使用实例
package com.happybks.nio.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.Date;
import java.util.Iterator;
import org.junit.Test;
public class TestNonBlockingNIO {
//客户端
@Test
public void client() throws IOException{
//1、获取通道
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",8888));
//2、切换非阻塞模式
socketChannel.configureBlocking(false);
//3、分配指定大小的缓冲区
ByteBuffer buf=ByteBuffer.allocate(1024);
//4、发送数据服务器
buf.put(new Date().toString().getBytes());
buf.flip();
socketChannel.write(buf);
buf.clear();
//5、关闭通道
socketChannel.close();
}
//服务端
@Test
public void server() throws IOException{
//1、获取通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//2、切换非阻塞模式
serverSocketChannel.configureBlocking(false);
//3、绑定连接
serverSocketChannel.bind(new InetSocketAddress(8888));
//4、获取选择器
Selector selector = Selector.open();
//5、将通道注册到选择器上(第二个选项参数叫做选择键,用于告诉选择器需要监控这个通道的什么状态或者说什么事件(读、写、连接、接受))
//选择键是整型值,如果需要监控该通道的多个状态或事件,可以将多个选择键用位运算符“或”“|”来连接
//这里服务端首先要监听客户端的接受状态
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//6、轮询式地获取选择器上已经“准备就绪”的事件
while(selector.select() > 0){
//7、获取当前选择中所有注册的“选择键(已就绪的监听事件)”
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext()){
//8、获取准备“就绪”的是事件
SelectionKey sk=iterator.next();
//9、判断是什么事件准备就绪
if(sk.isAcceptable()){
//10、若接受就绪,获取客户端连接
SocketChannel socketChannel = serverSocketChannel.accept();
//11、客户端连接socketChannel也需要切换非阻塞模式
socketChannel.configureBlocking(false);
//12、将该通道注册到选择器上,监控客户端socketChannel的读就绪事件
socketChannel.register(selector, SelectionKey.OP_READ);
}
else if(sk.isReadable()){
//13、获取当前选择器上“读就绪”状态的通道
SocketChannel socketChannel = (SocketChannel) sk.channel();
//14、读取数据
ByteBuffer buf=ByteBuffer.allocate(1024);
int len=0;
while((len=socketChannel.read(buf))>0){
buf.flip();
System.out.println(new String(buf.array(),0,len));
buf.clear();
}
}
//15、取消选择键SelectionKey
iterator.remove();
}
}
}
}
自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:
https://www.cnblogs.com/bclshuai/p/11380657.html
百度云盘下载地址:
链接:https://pan.baidu.com/s/1swkQzCIKI3g3ObcebgpIDg
提取码:mc8l
微信公众号获取最新的软件和视频介绍
QStockView

java非阻塞NIO和阻塞IO的更多相关文章
- JAVA中的NIO (New IO)
简介 标准的IO是基于字节流和字符流进行操作的,而JAVA中的NIO是基于Channel和Buffer进行操作的. 传统IO graph TB; 字节流 --> InputStream; 字节流 ...
- Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO
Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...
- JAVA阻塞(IO)和非阻塞(NIO)
查看这篇文章,了解更多关于Java的阻塞和非阻塞替代创建套接字的信息. 套接字使用TCP / IP传输协议,是两台主机之间的最后一块网络通信. 您通常不必处理它们,因为它们之上构建了协议,如HTTP或 ...
- java的高并发IO原理,阻塞BIO同步非阻塞NIO,异步非阻塞AIO
原文地址: IO读写的基础原理 大家知道,用户程序进行IO的读写,依赖于底层的IO读写,基本上会用到底层的read&write两大系统调用.在不同的操作系统中,IO读写的系统调用的名称可能不完 ...
- JAVA 中BIO,NIO,AIO的理解以及 同步 异步 阻塞 非阻塞
在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步 ...
- IO通信模型(二)同步非阻塞模式NIO(NonBlocking IO)
同步非阻塞模式(NonBlocking IO) 在非阻塞模式中,发出Socket的accept()和read()操作时,如果内核中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回一个信息.也 ...
- NIO之阻塞IO与非阻塞IO(包含Selector使用)
阻塞IO 传统的 IO 流都是阻塞式的. 也就是说,当一个线程调用 read() 或 write()时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务. 因此,在完成网络通信 ...
- NIO 之阻塞IO和非阻塞IO(转载)
阻塞模式 IO 我们已经介绍过使用 Java NIO 包组成一个简单的客户端-服务端网络通讯所需要的 ServerSocketChannel.SocketChannel 和 Buffer,我们这里整合 ...
- 【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?
通过上篇文章([死磕NIO]- 阻塞.非阻塞.同步.异步,傻傻分不清楚),我想你应该能够区分了什么是阻塞.非阻塞.异步.非异步了,这篇文章我们来彻底弄清楚什么是阻塞IO,非阻塞IO,IO复用,信号驱动 ...
随机推荐
- mongodb细讲
一. 关系型数据库(sql) 1.建表 二.非关系型数据库(nosql 98提出的概念) 1.不用建库建表数据直接存入就可 优缺点: 关系型:节约资源(学生姓名和课程名不重复出现),开发不方便(需先 ...
- codeforces-5
这题可害苦了我最后用了大哥的代码才过的 Diverse String #include<iostream> #include<cstdio> #include<strin ...
- 线性二次型调节器LQR/LQC算法解析及求解器代码(matlab)
参考链接:http://120.52.51.14/stanford.edu/class/ee363/lectures/dlqr.pdf 本文参考讲义中的第20页PPT,根据Hamilton-Jacob ...
- TypeError: '_io.TextIOWrapper' object does not support item assignment
纯小白 遇到的细节问题: 报错 一开始看到这个傻逼了 TypeError: '_io.TextIOWrapper' object does not support item assignment 其实 ...
- Hadoop 进程配置总结
HDFS: NameNode: core-site.xml <property> <name>fs.defaultFS</name> <value>hd ...
- python locust 性能测试:嵌套
TaskSet类和TaskSequence类可用于嵌套<可以在TaskSequences中嵌套TaskSets,反之亦然>: from locust import TaskSet, tas ...
- JAVA课堂测试之一位数组可视化
代码: package test;//求最大子数组 import java.util.Scanner; import javax.swing.JOptionPane; public class shu ...
- IP通信基础学习第四周(下)
选择子网掩码时,不总是使用整个八位作为屏蔽位. 在每个子网中,子网掩码是相同的. 在划分子网的情况下,判断两台主机是不是在同一子网中,需看它们的网络号与子网地址是不是相同的. 变长子网掩码VLSM,无 ...
- html2canvas截屏用法
<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8" ...
- 分享一个基于ssm框架下的webService接口开发
首先肯定是导入相关jar包 cxf-core-3.1.9.jar cxf-rt-bindings-soap-3.1.9.jar cxf-rt-bindings-xml-3.1.9.jar cxf-rt ...