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 ...
随机推荐
- 小白学Python-S3-day04-用户信息的增删改查、变更权限
一.用户信息 文件中每一行就是用户的详细信息,每一行是按照冒号为分隔符分成七段 第一段用户名,第二段密码占位符,第三段UID,第四段GID,第五段是描述信息,第六段是家目录.第七段是 是否 可以登录操 ...
- 理解Yarn的执行流程和组件作用
Yarn引入案例 1.学生找院长报到,院长给学生一个学号 2.院长比较忙,继续找主任处理学生事务 3.系主任找院办给学生分配资源(书本) 4.主任找张老师教授java 5.张老师给学生安排座位 6.学 ...
- SpringDataJpa——JpaRepository查询功能(转)
1.JpaRepository支持接口规范方法名查询.意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现,目前支持的关键字如下. Keyword Sample JPQL snippet ...
- ubuntu连接window系统
最后可以通过次命令挂载本地文件夹到远程电脑: rdesktop -a 24 -f -r disk:share-name=/home/lion/.m2/ 192.168.151.232
- OAuth2.0摘要
一.简介 不使用oauth2.0协议,资源所有者直接给需要使用资源的第三方应用共享凭据时,有这些问题: 需要直接共享给第三方应用凭据 需要服务器支持密码身份验证 凭据的访问权限过大,失去对访问时间和范 ...
- Hadoop 之 MapReduce原理
1.什么是MapReduce 答:简而言之,就是将一个大任务分成多个小的子任务(Map),并行执行后,合并结果(Reduce).下面举一个纸牌得栗子 2.MapReduce的运行流程 3.JobT ...
- [C++] 类的设计(2)——拷贝控制(1)
1.一个类通过定义五种特殊的成员函数来控制此类型对象的拷贝.移动.赋值和销毁:拷贝构造函数.拷贝赋值运算符.移动构造函数.移动赋值运算符和析构函数.(拷贝.移动.析构) 2.拷贝和移动构造函数定义 ...
- 转:LinkedHashMap和HashMap的比较使用
import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.uti ...
- 使Flask的url支持正则表达式以及一个api小demo
from flask import Flask from flask import jsonify from flask import request from werkzeug.routing im ...
- maven 3.6的安装
呵呵,按网上的步骤不能安装maven3.6,所以降低版本.因为3.6的没有bin文件夹. 下载地址:https://archive.apache.org/dist/maven/maven-3/3.5. ...