知识点整理-bio、nio的简单demo
- BIO
package com.io.bio; import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket; public class IOServer { /**
* Server服务端首先创建ServerSocket监听8000端口,然后创建线程不断调用阻塞方法 serversocket.accept()获取新的连接,当获取到新的连接给每条连接创建新的线程负责从该连接中读取数据,然后读取数据是以字节流的方式
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(); //接收新连接线程
new Thread(() -> {
try {
//(1)阻塞方法获取新的连接
Socket socket = serverSocket.accept(); //(2)每一个新的连接都创建一个线程,负责读取数据
new Thread(() -> {
try {
byte[] data = new byte[];
InputStream inputStream = socket.getInputStream();
while (true) {
int len;
//(3)按照字节流方式读取数据
while ((len = inputStream.read(data)) != -) {
System.out.println(new String(data, , len));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
package com.io.bio; import java.io.IOException;
import java.net.Socket;
import java.util.Date; public class IOClient { /**
* Client客户端连接服务端8000端口每隔2秒向服务端写带有时间戳的 "hello world"
*
* @param args
*/
public static void main(String[] args) {
new Thread(() -> {
try {
Socket socket = new Socket("127.0.0.1", );
while (true) {
try {
socket.getOutputStream().write((new Date() + ": hello world").getBytes());
socket.getOutputStream().flush();
Thread.sleep();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
传统的IO模型每个连接创建成功都需要一个线程来维护,每个线程包含一个while死循环,那么1w个连接对应1w个线程,继而1w个while死循环带来如下几个问题:
1.线程资源受限:线程是操作系统中非常宝贵的资源,同一时刻有大量的线程处于阻塞状态是非常严重的资源浪费,操作系统耗不起;
2.线程切换效率低下:单机CPU核数固定,线程爆炸之后操作系统频繁进行线程切换,应用性能急剧下降;
3.数据读写是以字节流为单位效率不高:每次都是从操作系统底层一个字节一个字节地读取数据.
- NIO
package com.io.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.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set; public class NIOServer { /**
* serverSelector负责轮询是否有新的连接,clientSelector负责轮询连接是否有数据可读.
* 服务端监测到新的连接不再创建一个新的线程,而是直接将新连接绑定到clientSelector上,这样不用IO模型中1w个while循环在死等
* clientSelector被一个while死循环包裹,如果在某一时刻有多条连接有数据可读通过 clientSelector.select(1)方法轮询出来进而批量处理
* 数据的读写以内存块为单位
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Selector serverSelector = Selector.open();
Selector clientSelector = Selector.open(); new Thread(() -> {
try {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress());
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(serverSelector, SelectionKey.OP_ACCEPT); while (true) {
// 轮询监测是否有新的连接
if (serverSelector.select() > ) {
Set<SelectionKey> selectionKeys = serverSelector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey selectionKey = keyIterator.next();
if (selectionKey.isAcceptable()) {
try {
//(1)每来一个新连接不需要创建一个线程而是直接注册到clientSelector
SocketChannel socketChannel = ((ServerSocketChannel) selectionKey.channel()).accept();
socketChannel.configureBlocking(false);
socketChannel.register(clientSelector, SelectionKey.OP_READ);
} finally {
keyIterator.remove();
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start(); new Thread(() -> {
try {
while (true) {
// (2)批量轮询是否有哪些连接有数据可读
if (clientSelector.select() > ) {
Set<SelectionKey> selectionKeys = serverSelector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey selectionKey = keyIterator.next();
if (selectionKey.isReadable()) {
try {
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate();
//(3)读取数据以块为单位批量读取
socketChannel.read(byteBuffer);
byteBuffer.flip();
System.out.println(Charset.defaultCharset().newDecoder().decode(byteBuffer)
.toString());
} finally {
keyIterator.remove();
selectionKey.interestOps(SelectionKey.OP_READ);
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
1.线程资源受限:NIO编程模型新来一个连接不再创建一个新的线程,把这条连接直接绑定到某个固定的线程,然后这条连接所有的读写都由该线程来负责.把这么多while死循环变成一个死循环,这个死循环由一个线程控制,一条连接来了,不创建一个while死循环去监听是否有数据可读,直接把这条连接注册到Selector上,然后通过检查Selector批量监测出有数据可读的连接进而读取数据.
2.线程切换效率低下:线程数量大大降低,线程切换效率因此也大幅度提高.
3.数据读写是以字节流为单位效率不高:NIO维护一个缓冲区每次从这个缓冲区里面读取一块的数据,数据读写不再以字节为单位,而是以字节块为单位.
知识点整理-bio、nio的简单demo的更多相关文章
- C#初级知识点整理及VS的简单使用
C#预处理器指令#define #undef 声明一个不需赋值的变量注意的一点事它必须放到using 上面,如 #define TEST using System.xxx; public class ...
- NIO的简单Demo
package jesse.test1; import java.io.IOException; import java.net.InetAddress; import java.net.InetSo ...
- tomcat bio nio apr 模式性能测试
转自:tomcat bio nio apr 模式性能测试与个人看法 11.11活动当天,服务器负载过大,导致部分页面出现了不可访问的状态.那后来主管就要求调优了,下面是tomcat bio.nio.a ...
- Netty5序章之BIO NIO AIO演变
Netty5序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使 ...
- Netty序章之BIO NIO AIO演变
Netty序章之BIO NIO AIO演变 Netty是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络服务器和客户端程序.Netty简化了网络程序的开发,是很多框架和公司都在使用 ...
- BIO,NIO,AIO总结
熟练掌握 BIO,NIO,AIO 的基本概念以及一些常见问题是你准备面试的过程中不可或缺的一部分,另外这些知识点也是你学习 Netty 的基础. BIO,NIO,AIO 总结 1. BIO (Bloc ...
- (转)也谈BIO | NIO | AIO (Java版)
原文地址: https://my.oschina.net/bluesky0leon/blog/132361 关于BIO | NIO | AIO的讨论一直存在,有时候也很容易让人混淆,就我的理解,给出一 ...
- 拿搬东西来解释udp tcpip bio nio aio aio异步
[群主]雷欧纳德简单理解 tcpip是有通信确认的面对面通信 有打招呼的过程 有建立通道的过程 有保持通道的确认 有具体传输udp是看到对面的人好像在对面等你 就往对面扔东西[群主]雷欧 ...
- 也谈BIO | NIO | AIO (Java版--转)
关于BIO | NIO | AIO的讨论一直存在,有时候也很容易让人混淆,就我的理解,给出一个解释: BIO | NIO | AIO,本身的描述都是在Java语言的基础上的.而描述IO,我们需要从两个 ...
随机推荐
- Wannafly挑战赛24-A-石子游戏--【思维题】
链接:https://www.nowcoder.com/acm/contest/186/A 来源:牛客网 石子游戏 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他 ...
- login.exp
#!/usr/bin/expect ] ] ] ] spawn ssh -p $user@$host expect { "*yes/no*" {send "yes\r&q ...
- django.db.utils.OperationalError: (1050, "Table 'article_category' already exists")
(转自:https://blog.csdn.net/huanhuanq1209/article/details/77884014) 执行manage.py makemigrations 未提示错误信息 ...
- Codeforces Round #539 (Div. 1) 1109F. Sasha and Algorithm of Silence's Sounds LCT+线段树 (two pointers)
题解请看 Felix-Lee的CSDN博客 写的很好,不过最后不用判断最小值是不是1,因为[i,i]只有一个点,一定满足条件,最小值一定是1. CODE 写完就A,刺激. #include <b ...
- P2272 [ZJOI2007]最大半连通子图 tarjan+DP
思路:$tarjan+DP$ 提交:1次 题解:首先对于一个强连通分量一定是一个半连通分量,并且形成的半连通分量的大小一定是它的$size$,所以我们先缩点. 这样,我们相当于要在新的$DAG$上找一 ...
- 001_FreeRTOS中断配置
(一)优先级看:022_STM32中断优先级分组解析 (二)FreeRTOS的中断配置中没有处理亚优先级(响应优先级)的情况,所以只能配置成组4,16个都为抢占优先级 (三)此宏用来设置 MCU 使用 ...
- mysql慢查询日志查找与分析
mysql下执行SHOW VARIABLES LIKE '%slow_query_log%' 上图我这是本地的mysql,慢查询没开. slow_query_log :ON和OFF分别表示慢查询有没有 ...
- luogu 4909 [Usaco2006 Mar]Ski Lift 缆车支柱 动态规划
可以出模拟赛T1? #include <bits/stdc++.h> #define N 5002 #define inf 1000000 #define setIO(s) freopen ...
- 网络流24题 P2766 最长不下降子序列问题
题目描述 «问题描述: 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次 ...
- 2018CCPCFINAL B Balance of the Force 枚举最大值
题意 n个人能选择黑暗面和光明面,选择两个面分别能获得\(L_i\)和\(R_i\)的力量,有m对人不能选择同一面,问n个人的力量中的最大值-最小值尽可能小为多少. \(1<=n<=2\t ...