Java中NIO及基础实现
NIO:同步非阻塞IO
来源:BIO是同步阻塞IO操作,当线程在处理任务时,另一方会阻塞着等待该线程的执行完毕,为了提高效率,,JDK1.4后,引入NIO来提升数据的通讯性能
NIO中采用Reactor设计模式,注册的汇集点为Selector,NIO有三个主要组成部分:Channel(通道)、Buffer(缓冲区)、Selector(选择器)
Reactor设计模式:Reactor模式是一种被动事件处理模式,即当某个特定事件发生时触发事件,可参考,https://blog.csdn.net/feimataxue/article/details/7642638,https://www.cnblogs.com/bitkevin/p/5724410.html
NIO采用了轮询的方式来观察事件是否执行完毕,如:A让B打印某个文件,BIO会一直等待着B返回,期间自己不做其他事情,而NIO则会不断的询问B是否完成,未完成则处理自己的时,直至B完成
Channel(通道):Channel是一个对象,可以通过它读取和写入数据
Selector(对象选择器): Selector是一个对象,它可以注册到很多个Channel上,监听各个Channel上发生的事件,并且能够根据事件情况决定Channel读写
代码实现:(此实现参考网络上可用的例子)
NIO客户端实现:
package com.learn.nio.client; import com.study.info.HostInfo;
import com.study.util.InputUtil; import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel; public class NIOEchoClient { public static void main(String[] args) throws Exception{
SocketChannel clientChannel = SocketChannel.open();
clientChannel.connect(new InetSocketAddress(HostInfo.HOST_NAME,HostInfo.PORT));
ByteBuffer buffer = ByteBuffer.allocate(50);
boolean flag = true;
while (flag){
buffer.clear();
String input = InputUtil.getString("请输入待发送的信息:").trim();
buffer.put(input.getBytes()); //将数据存入缓冲区
buffer.flip(); // 重置缓冲区
clientChannel.write(buffer); //发送数据
buffer.clear();
int read = clientChannel.read(buffer);
buffer.flip();
System.err.print(new String(buffer.array(), 0, read));
if("byebye".equalsIgnoreCase(input)){
flag = false;
}
}
clientChannel.close();
}
}
NIO服务端实现:
package com.learn.nio.server; import com.study.info.HostInfo; 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;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class NIOEchoServer { private static class EchoClientHandle implements Runnable { //客户端
private SocketChannel clientChannel;
// 循环结束标记
private boolean flag = true;
public EchoClientHandle(SocketChannel clientChannel){
this.clientChannel = clientChannel;
} @Override
public void run() {
ByteBuffer byteBuffer = ByteBuffer.allocate(50);
try {
while (this.flag){
byteBuffer.clear();
int read = this.clientChannel.read(byteBuffer);
String msg = new String(byteBuffer.array(), 0, read).trim();
String outMsg = "【Echo】" + msg + "\n"; // 回应信息
if("byebve".equals(msg)){
outMsg = "会话结束,下次再见!";
this.flag = false;
}
byteBuffer.clear();
byteBuffer.put(outMsg.getBytes()); //回传信息放入缓冲区
byteBuffer.flip();
this.clientChannel.write(byteBuffer);// 回传信息
}
}catch (Exception e){
e.printStackTrace();
}
}
} public static void main(String[] args) throws Exception{
// 为了性能问题及响应时间,设置固定大小的线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
// NIO基于Channel控制,所以有Selector管理所有的Channel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 设置为非阻塞模式
serverSocketChannel.configureBlocking(false);
// 设置监听端口
serverSocketChannel.bind(new InetSocketAddress(HostInfo.PORT));
// 设置Selector管理所有Channel
Selector selector = Selector.open();
// 注册并设置连接时处理
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("服务启动成功,监听端口为:" + HostInfo.PORT);
// NIO使用轮询,当有请求连接时,则启动一个线程
int keySelect = 0;
while ((keySelect = selector.select()) > 0){
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey next = iterator.next();
if(next.isAcceptable()){ // 如果是连接的
SocketChannel accept = serverSocketChannel.accept();
if(accept != null){
executorService.submit(new EchoClientHandle(accept));
}
iterator.remove();
}
}
}
executorService.shutdown();
serverSocketChannel.close();
}
}
工具类:
package com.study.util; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader; public class InputUtil {
private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in)); private InputUtil(){
} public static String getString(String prompt){
boolean flag = true; //数据接受标记
String str = null;
while (flag){
System.out.println(prompt);
try {
str = KEYBOARD_INPUT.readLine(); // 读取一行数据
if(str == null || "".equals(str)){
System.out.println("数据输入错误,不允许为空!");
}else {
flag = false;
}
} catch (IOException e) {
e.printStackTrace();
}
}
return str;
}
}
package com.study.info; public calss HostInfo {
public static final String HOST_NAME = "localhost";
public static final int PORT = 9999;
}
NIO结构参考文章: https://www.cnblogs.com/sxkgeek/p/9488703.html#_label2
Java中NIO及基础实现的更多相关文章
- 第87节:Java中的Bootstrap基础与SQL入门
第87节:Java中的Bootstrap基础与SQL入门 前言复习 什么是JQ? : write less do more 写更少的代码,做更多的事 找出所有兄弟: $("div" ...
- 第90节:Java中的Linux基础
第90节:Java中的Linux基础 linux是装载虚拟机上面的: JDK依赖包: yum install glibc.i686 MYSQL依赖包: yum -y install libaio.so ...
- 并发王者课-铂金1:探本溯源-为何说Lock接口是Java中锁的基础
欢迎来到<并发王者课>,本文是该系列文章中的第14篇. 在黄金系列中,我们介绍了并发中一些问题,比如死锁.活锁.线程饥饿等问题.在并发编程中,这些问题无疑都是需要解决的.所以,在铂金系列文 ...
- java基础---->java中nio的使用(一)
JDK 1.4 中引入的新输入输出 (NIO) 库在标准 Java 代码中提供了高速的.面向块的 I/O.今天我们就简单的学习一下nio的知识.我笑,便面如春花,定是能感动人的,任他是谁. nio的简 ...
- Java中的框架基础面试知识
spring mvc 工作机制(原理): DispatcherServlet主要用作职责调度工作,本身主要用于控制流程 Spring mvc运行原理 1.springmvc将所有的请求都提交给Disp ...
- Java中NIO、BIO、AIO相关概念及应用场景
1.同步阻塞IO(JAVA BIO):同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时,服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通 ...
- Java中NIO的简单介绍
NIO基本介绍 Java NIO(New IO) 也有人称之为Java non-blocking IO 是从Java1.4版本开始引入的一个新的IO API,可以代替标准的IO API.NIO与原来的 ...
- 第86节:Java中的JQuery基础
第86节:Java中的JQuery 前言复习 定时器: setInterval clearInterval setTimeout clearTimeout 显示: img.style.display ...
- java中的多线程 // 基础
java 中的多线程 简介 进程 : 指正在运行的程序,并具有一定的独立能力,即 当硬盘中的程序进入到内存中运行时,就变成了一个进程 线程 : 是进程中的一个执行单元,负责当前程序的执行.线程就是CP ...
随机推荐
- Elasticsearch 顶尖高手(1)
1.什么是搜索? 百度 = 搜索,这是不对的 垂直搜索(站内搜索) 互联网的搜索:电商网站,招聘网站,新闻网站,各种app IT系统的搜索:OA软件,办公自动化软件,会议管理,项目管理,员工管理 搜索 ...
- Spring的事件监听机制
最近公司在重构广告系统,其中核心的打包功能由广告系统调用,即对apk打包的调用和打包完成之后的回调,需要提供相应的接口给广告系统.因此,为了将apk打包的核心流程和对接广告系统的业务解耦,利用了spr ...
- SpringCloud学习笔记(1):Eureka注册中心
简介 Eureka是Netflix开源的基于rest的服务治理方案,分为Server端和Client端,Server端为注册中心,其他微服务通过Client端连接Server端进行服务的注册和发现. ...
- CentSO7.6下部署Maridb Galera Cluster 实践记录(二)
早上三个节点的数据库都启动正常,下午上班就都不行了,哎,VM啊,中午就是让主机休息了一些而已么. 今天继续折腾中,第二天再来一遍:重启第一台服务器上的galera时竟然报错了:错误如下: It ...
- 未能加载文件或程序集“Renci.SshNet, Version=2016.1.0.0, Culture=neutral, PublicKeyToken=……”
emmmm~ 这是一个让人烦躁有悲伤的问题~ 背景 我也不知道什么原因,用着用着,正好好的,就突然报了这种问题~ 未能加载文件或程序集“Renci.SshNet, Version=2016.1.0.0 ...
- MySQL5.7初始化后5种密码重置方法
前言:由于好几次安装MySQL5.7后一直被重置密码所困扰,因此特意整理重置的方法 安装MySQL5.7 [root@node1 db]# ll 以下的rpm安装包可以随处下载 total 40235 ...
- hive 元数据解析
在使用Hive进行开发时,我们往往需要获得一个已存在hive表的建表语句(DDL),然而hive本身并没有提供这样一个工具. 要想还原建表DDL就必须从元数据入手,我们知道,hive的元数据并不存放在 ...
- git windows 安装 - Github同步 / Vscode源代码管理:Git 安装操作
github上创建立一个项目 登录github网站,在github首页,点击页面右下角"New Repository" 最后点击"Create Repository&qu ...
- 2019 DevOps 必备面试题——配置管理篇
原文地址:https://medium.com/edureka/devops-interview-questions-e91a4e6ecbf3 原文作者:Saurabh Kulshrestha 翻译君 ...
- LayUI 上传IE11上传格式错误之后, layer.load(1)的动画一直在,没有关闭(仅限IE11)
这个问题,测试反馈的时候,有丝丝的不相信,毕竟layui大家都是那么用的,结果后来用最简单的测试,发现确实会出现动画一直在的情况,如下: 上网搜索,也没发现一些有效的信息,最后就是自己读upload. ...