BIO与NIO
BIO与NIO
1.传统BIO
(1)特点
- 面向数据流
- 阻塞式传输
- 一个客户端对应一个线程
- 在客户机增多的情况下,线程资源随之增多,会造成cpu资源枯竭
(2)需求
客户机向服务器输出字符串,逐一在服务器器上打印显示。类似一个简陋的聊天室功能。
(3)代码示例
服务器程序TimeServer.java
package com.xm.bio; import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket; public class TimeServer { public static void main(String[] args) throws IOException {
int port = 8080;
if(args != null && args.length>0) {
try {
port = Integer.parseInt(args[0]); } catch (Exception e) { }
} ServerSocket server = null;
try {
server = new ServerSocket(port);
System.out.println("开启服务器:"+server.getLocalSocketAddress());
Socket socket = null;
while(true) {
socket = server.accept();
new Thread(new TimeServerHandle(socket)).start();
}
} finally {
if(server != null) {
System.out.println("服务器已关闭!");
server.close();
server = null;
}
} } }服务器处理客户机进程TimeServerHandle.java
package com.xm.bio; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Date; public class TimeServerHandle implements Runnable { private Socket socket; public TimeServerHandle(Socket socket) {
this.socket = socket;
} @Override
public void run() {
System.out.println(socket.getInetAddress().toString()+"客户机已连接");
BufferedReader in = null;
PrintWriter out = null;
BufferedReader wt = null;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
wt = new BufferedReader(new InputStreamReader(System.in));
while(true) {
System.out.println(in.readLine());
}
} catch (Exception e) { } finally {
if(in != null) {
try {
in.close();
in = null;
} catch (IOException e) {
e.printStackTrace();
}
}
if(out != null) {
out.close();
out = null;
}
if(socket != null) {
try {
socket.close();
socket = null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
} } }客户端程序TimeClient.java
package com.xm.bio; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException; public class TimeClient { public static void main(String[] args) {
int port = 8080;
String host = "127.0.0.1";
Socket socket = null;
BufferedReader in = null;
BufferedReader wt = null;
PrintWriter out = null;
try {
socket = new Socket(host, port);
wt = new BufferedReader(new InputStreamReader(System.in));
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
String body = null;
while(true) {
String str = wt.readLine();
out.println(str);
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
wt.close();
in.close();
out.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } } }
2.NIO
(1)NIO特点
1.面向缓冲区
2.传输方式为管道传输
3.非阻塞
4.支持大并发下的io处理
(2)NIO下的本地文件传输
内存映射下的缓冲通道
package com.xm.nio; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.Duration;
import java.time.Instant; import org.junit.jupiter.api.Test; public class NIOFileDemo { /**
* 1.通过流获取通道
*/
@Test
public void test1() {
Instant begin = Instant.now();
//1.定义文件流
FileInputStream fis = null;
FileOutputStream fos = null;
//2.获取通道
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
fis = new FileInputStream("1.jpg");
fos = new FileOutputStream("2.jpg"); inChannel = fis.getChannel();
outChannel = fos.getChannel(); //3.定义缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024); //4.读取数据到缓冲区,再从缓冲区写入到文件
while(inChannel.read(buffer) != -1) {
//切换到读模式
buffer.flip();
//写操作到管道
outChannel.write(buffer);
//清空buffer
buffer.clear();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//5.关闭通道和流
if(inChannel != null) {
try {
inChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(outChannel != null) {
try {
outChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fis != null) { try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
Instant end = begin.plus(Duration.ofSeconds(10));
System.out.println("Difference in milliseconds : " + Duration.between(begin, end).toMillis());
} /**
* 通过文件获取管道
*/
@Test
public void test2() {
Instant begin = Instant.now();
FileChannel inChannel =null;
FileChannel outChannel = null;
try {
inChannel =FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
/**
* StandardOpenOption.CREATE与StandardOpenOption.CREATE_NEW的区别
* 1.StandardOpenOption.CREATE:无则创建,有则覆盖
* 2.StandardOpenOption.CREATE_NEW:无则创建,有则报错
*/
outChannel =FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
//3.定义缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024); //4.读取数据到缓冲区,再从缓冲区写入到文件
while(inChannel.read(buffer) != -1) {
//切换到读模式
buffer.flip();
//写操作到管道
outChannel.write(buffer);
//清空buffer
buffer.clear();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//5.关闭通道和流
if(inChannel != null) {
try {
inChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(outChannel != null) {
try {
outChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Instant end = begin.plus(Duration.ofSeconds(10));
System.out.println("Difference in milliseconds : " + Duration.between(begin, end).toMillis()); } }物理映射下的缓冲通道
package com.xm.nio; import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.Duration;
import java.time.Instant; import org.junit.Test; public class NIOFileDemo2 { /**
* 使用直接缓冲区传输
*/
@Test
public void test1() {
Instant begin = Instant.now();
FileChannel inChannel = null;
FileChannel outChannel = null; try {
//1.开启通道
inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE,StandardOpenOption.READ); //2.定义物理缓冲区
MappedByteBuffer inBuffer = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outBuffer = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size()); //3.缓冲区读写操作
byte[] dst = new byte[inBuffer.limit()];
inBuffer.get(dst);
outBuffer.put(dst); } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//4.关闭通道
if(null != inChannel) { try {
inChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(null != outChannel) { try {
outChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Instant end = begin.plus(Duration.ofSeconds(10));
System.out.println("Difference in milliseconds : " + Duration.between(begin, end).toMillis());
} /**
* 通道之间的传输
*/
@Test
public void test2() {
Instant begin = Instant.now();
FileChannel inChannel = null;
FileChannel outChannel = null;
//获取通道
try {
inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
outChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE); //通道间传输
//1.to操作
//inChannel.transferTo(0, inChannel.size(), outChannel);
//2.from操作
outChannel.transferFrom(inChannel, 0, inChannel.size());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//4.关闭通道
if(null != inChannel) { try {
inChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(null != outChannel) { try {
outChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Instant end = begin.plus(Duration.ofSeconds(10));
System.out.println("Difference in milliseconds : " + Duration.between(begin, end).toMillis());
} }
(3)NIO下的网络传输
阻塞式
服务端程序
package com.xm.nio.block; 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;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Scanner; public class NIOServer { public static void main(String[] args) throws IOException { int port = 8989; //1.获取通道
ServerSocketChannel serverChannel = ServerSocketChannel.open(); //2.绑定端口号
serverChannel.bind(new InetSocketAddress(port)); //3.获取客户端连接
SocketChannel socketChannel = serverChannel.accept(); //定义文件传输通道
FileChannel outChannel = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(socketChannel.read(buffer)!=-1) {
buffer.flip();
outChannel.write(buffer);
buffer.clear();
} outChannel.close();
socketChannel.close(); } }客户端程序
package com.xm.nio.block; import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; public class NIOClient { public static void main(String[] args) throws IOException {
int port = 8989;
//1.获取通道
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", port)); //2.获取文件通道
FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
inChannel.transferTo(0, inChannel.size(), socketChannel); //3.关闭通道
inChannel.close();
socketChannel.close(); } }
非阻塞式
服务端程序
package com.xm.nio.noblock; 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.ArrayList;
import java.util.Iterator;
import java.util.List; public class NIOServer { public static void main(String[] args) throws IOException { int port = 8989; //1.开启通道
ServerSocketChannel serverChannel = ServerSocketChannel.open(); //2.绑定端口号
serverChannel.bind(new InetSocketAddress(port)); //3.设置非阻塞
serverChannel.configureBlocking(false); //4.开启选择器
Selector selector = Selector.open(); //5.注册连接监听
serverChannel.register(selector, SelectionKey.OP_ACCEPT); List<SocketChannel> channels = new ArrayList<>(); while(selector.select() > 0) {
Iterator<SelectionKey> keys = selector.selectedKeys().iterator(); while(keys.hasNext()) {
SelectionKey key = keys.next();
if(key.isAcceptable()) {
SocketChannel socketChannel = serverChannel.accept();
channels.add(socketChannel);
System.out.println("客户端连接成功:"+socketChannel.getLocalAddress()+" hashcode:"+socketChannel.hashCode());
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if(key.isReadable()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer dst = ByteBuffer.allocate(1024);
int len;
while(-1 != (len=socketChannel.read(dst))) {
dst.flip();
System.out.println(new String(dst.array(),0,len));
/*for(SocketChannel sChannel:channels) {
if(sChannel != socketChannel) {
dst.flip();
sChannel.write(dst);
}
}*/
dst.clear();
}
}
} keys.remove();
} } }客户端
package com.xm.nio.noblock; import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Iterator;
import java.util.Scanner; public class NIOClient{ SocketChannel socketChannel; public NIOClient() throws IOException {
int port = 8989;
//1.获取通道
socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", port));
//2.设置异步非阻塞
socketChannel.configureBlocking(false); //2.获取文件通道
FileChannel inChannel = FileChannel.open(Paths.get("1.md"), StandardOpenOption.READ);
inChannel.transferTo(0, inChannel.size(), socketChannel); //3.关闭通道
inChannel.close();
socketChannel.close(); } public static void main(String[] args) {
try {
new NIOClient();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
BIO与NIO的更多相关文章
- Java BIO、NIO、AIO 学习(转)
转自 http://stevex.blog.51cto.com/4300375/1284437 先来个例子理解一下概念,以银行取款为例: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Ja ...
- BIO、NIO与NIO.2的区别与联系
BIO.NIO.NIO.2之间的区别主要是通过同步/异步.阻塞/非阻塞来进行区分的 同步: 程序与操作系统进行交互的时候采取的是问答的形式 异步: 程序与操作系统取得连接后,操作系统会主动通知程序消息 ...
- Java BIO、NIO、AIO-------转载
先来个例子理解一下概念,以银行取款为例: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写). 异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Ja ...
- BIO与NIO、AIO的区别
IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. 一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个Serve ...
- JAVA中IO技术:BIO、NIO、AIO
1.同步异步.阻塞非阻塞概念 同步和异步是针对应用程序和内核的交互而言的. 阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作 ...
- Java IO 之 BIO、NIO、AIO
1.BIO.NIO.AIO解释 Java BIO : 同步并阻塞 (Blocking IO) 一个连接一个线程 即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不 ...
- Tomcat在Linux服务器上的BIO、NIO、APR模式设置
一.BIO.NIO.AIO 先了解四个概念: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写). 异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时, ...
- tomcat并发优化之三种接收处理请求方式(BIO、NIO、APR)介绍
原文链接:http://blog.csdn.net/xyang81/article/details/51502766 Tomcat支持三种接收请求的处理方式:BIO.NIO.APR 1>.BIO ...
- 操作系统层面聊聊BIO,NIO和AIO (epoll)
BIO 有了Block的定义,就可以讨论BIO和NIO了.BIO是Blocking IO的意思.在类似于网络中进行read, write, connect一类的系统调用时会被卡住. 举个例子,当用re ...
- Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为 ...
随机推荐
- shell查看内存
<1>jps<2>ps<3>free<4>df<5>top jps: 很多Java命令都在jdk的JAVA_HOME/bin/目录下面,jp ...
- Barty's Computer 字典树
https://nanti.jisuanke.com/t/17122 Barty have a computer, it can do these two things. Add a new stri ...
- Java基础03-类型转换
1.自动转换 int->double char->String 例:double a=10; 2.强制类型转换 (类型名)表达式 注意:String不能强制转化为char public c ...
- python单元测试框架-unittest(四)之用例综合框架管理
简述为何如要框架? 前面测试用例与执行都是写在一个文件,当用例数量不断增加的时候,用例的执行与管理变得非常麻烦,因此需要对用例根据具体的功能模块来使用单独的模块来管理.就像一所学校要根据不同年级进行分 ...
- python3+Appium自动化10-日志收集
日志概述 日志作用 日志是定位问题的重要手段 日志级别 级别 何时使用 DEBUG 调试信息,也是最详细的日志信息 INFO 证明事情按预期工作 WARNING 表明发生了一些意外,或者不就的将来(如 ...
- ErlangC 最佳人力效益指标
以平均服务时间(AHT)180秒,顾客来电量每15分钟150通以及服务目标时间在20秒内为例子说明最佳人力效益指标.此假设条件下由Erlang C模拟器的结果如下图, 假设我希望客服中心的期望服务水准 ...
- mapreduce总结
一.mapreduce简介 MapReduce是一种分布式计算模型,是hadoop的核心组件之一,是Google提出的,主要用于搜索领域,解决海量数据的计算问题. MR有两个阶段组成:Map和Redu ...
- echarts自适应宽度
const myChartContainer = document.getElementById( id ); const resizeMyChartContainer = function () { ...
- python面试题——数据库和缓存(46题)
1.列举常见的关系型数据库和非关系型都有那些? 2.MySQL常见数据库引擎及比较? 3.简述数据三大范式? 4.什么是事务?MySQL如何支持事务? 5.简述数据库设计中一对多和多对多的应用场景? ...
- sass随笔
一.前期准备 sass基于ruby (1) 安装ruby 从http://rubyinstaller.org/downloads/下载 双击下载的程序进行安装,勾选如下图的选 ...