BIO

IO:BIO:Blocking                OIO:old

NIO:Non-Blocking         NIO:new

BIO问题:        会创建很多的线程clone,占用很多COU资源,来回拉扯调度;

问题的根源是“阻塞”。

  • 1.每个Socket接收到,都会创建一个线程,线程的竞争、切换上下文影响性能;

  • 2.每个线程都会占用栈空间和CPU资源;

  • 3.并不是每个socket都进行IO操作,无意义的线程处理;

  • 4.客户端的并发访问增加时。服务端将呈现1:1的线程开销,访问量越大,系统将发生线程栈溢出,线程创建失败,最终导致进程宕机或者僵死,从而不能对外提供服务。

package com.wang;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;public class BIO {public static void main(String[] args) throws IOException {//实际上是开启了一个线程ServerSocket server = new ServerSocket(9090, 20);System.out.println("step1: new ServerSocket(9090, 20)");while (true) {Socket client = server.accept();System.out.println("step2: client\t"+client.getPort());new Thread(new Runnable() {@Overridepublic void run() {InputStream in = null;try {in = client.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(in));while (true){//阻塞String data = reader.readLine();if (data != null){System.out.println(data);}else {client.close();break;}}}catch (Exception e){e.printStackTrace();}}});}}
}

Linux:追踪(JDK1.4以下才能看到效果):

strace -ff -o log jdk/1.4bin/java SocketBIO
ll

trace:追踪 kernel 与 程序 的调用关系

vim xx.9837

客户端连接后,accept()就不阻塞了

clone()了一个线程之后,又重新回到accept()阻塞

查看创建的新线程文件:

新线程又开始阻塞了,等待读取数据 rev(5,

用tail -f ooxx.9878(新创建的线程)

当client发送数据后 rev(5,接收数据,打印完之后,又重新阻塞等待接受数据:

NIO

在操作系统层面。解决阻塞问题靠kernerl来解决。

jdk1.8:

package com.wang;import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;public class NIO {public static void main(String[] args) throws IOException, InterruptedException {LinkedList<SocketChannel> clients = new LinkedList<>();ServerSocketChannel ss = ServerSocketChannel.open();ss.bind(new InetSocketAddress(9090));//不阻塞ss.configureBlocking(false);ss.setOption(StandardSocketOptions.TCP_NODELAY, false);//        StandardSocketOptions.SO_KEEPALIVE
//        StandardSocketOptions.SO_LINGER
//        StandardSocketOptions.SO_RCVBUF
//        StandardSocketOptions.SO_SNDBUF
//        StandardSocketOptions.SO_REUSEADDRwhile (true) {
//            Thread.sleep(1000);SocketChannel client = ss.accept();     // -1 nullif (client == null) {
//                System.out.println("null.....");} else {client.configureBlocking(false);int port = client.socket().getPort();System.out.println("client.port:" + port);clients.add(client);}ByteBuffer buffer = ByteBuffer.allocateDirect(4096);//遍历已连接进来的客户端for (SocketChannel c : clients) {int num = c.read(buffer);   // >0  0  -1if (num > 0) {buffer.flip();byte[] bytes = new byte[buffer.limit()];buffer.get(bytes);String s = new String(bytes);System.out.println(c.socket().getPort() + " : " + s);}}}}
}
ss.configureBlocking(false);

if(client == null)

多路复用器

上述NIO中,需要轮询每个连接的客户端,不一定每个客户端都有数据发送过来,也就是每一次轮询不一定是“有效的”,造成轮询“徒劳”。

        while (true) {
//            Thread.sleep(1000);SocketChannel client = ss.accept();     // -1 null....//遍历已连接进来的客户端for (SocketChannel c : clients) {....

解决“徒劳”问题靠kernerl来解决。

多条路复用一个电话机:

优点:减少了系统调用的数量

弊端:每次都要传递大量的fd数据给内核

每次都要从头遍历

/**客户端*/
public class Client {public static void main(String[] args) throws Exception {//1. 获取通道SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999));//2. 切换非阻塞模式sChannel.configureBlocking(false);//3. 分配指定大小的缓冲区ByteBuffer buf = ByteBuffer.allocate(1024);//4. 发送数据给服务端Scanner scan = new Scanner(System.in);while(scan.hasNext()){String str = scan.nextLine();buf.put((new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(System.currentTimeMillis())+ "\n" + str).getBytes());buf.flip();sChannel.write(buf);buf.clear();}//5. 关闭通道sChannel.close();}
}/**服务端*/
public class Server {public static void main(String[] args) throws IOException {//1. 获取通道ServerSocketChannel ssChannel = ServerSocketChannel.open();//2. 切换非阻塞模式ssChannel.configureBlocking(false);//3. 绑定连接ssChannel.bind(new InetSocketAddress(9999));//4. 获取选择器Selector selector = Selector.open();//5. 将通道注册到选择器上, 并且指定“监听接收事件”ssChannel.register(selector, SelectionKey.OP_ACCEPT);//6. 轮询式的获取选择器上已经“准备就绪”的事件while (selector.select() > 0) {System.out.println("轮一轮");//7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)”Iterator<SelectionKey> it = selector.selectedKeys().iterator();while (it.hasNext()) {//8. 获取准备“就绪”的是事件SelectionKey sk = it.next();//9. 判断具体是什么事件准备就绪if (sk.isAcceptable()) {//10. 若“接收就绪”,获取客户端连接SocketChannel sChannel = ssChannel.accept();//11. 切换非阻塞模式sChannel.configureBlocking(false);//12. 将该通道注册到选择器上sChannel.register(selector, SelectionKey.OP_READ);} else if (sk.isReadable()) {//13. 获取当前选择器上“读就绪”状态的通道SocketChannel sChannel = (SocketChannel) sk.channel();//14. 读取数据ByteBuffer buf = ByteBuffer.allocate(1024);int len = 0;while ((len = sChannel.read(buf)) > 0) {buf.flip();System.out.println(new String(buf.array(), 0, len));buf.clear();}}//15. 取消选择键 SelectionKeyit.remove();}}}
}

IO-BIO NIO相关推荐

  1. Java IO BIO NIO

    Java IO BIO NIO 一.Java I/O概述 1.1 什么是流 1.2 流的分类 1.3 字符流 1.3.1 Reader 1.3.2 Writer 1.4 字节流 1.4.1 Input ...

  2. JAVA IO : BIO NIO AIO

    JAVA IO : BIO NIO AIO 同步异步.阻塞非阻塞概念 同步与异步 阻塞与非阻塞 IO VS NIO VS AIO 面向流与面向缓冲 阻塞与非阻塞IO BIO.NIO.AIO的JAVA实 ...

  3. Java之IO,BIO,NIO,AIO知多少?

    开心一笑 [一女人:"我真不放心丈夫,他准备到湖中心水最深的地方把猫扔掉."邻居:"那有什么不放心的?"女人:"猫已回家一钟头了!"] 提出 ...

  4. Java之IO,BIO,NIO,AIO

    2019独角兽企业重金招聘Python工程师标准>>> 参考文献一 IO基础知识回顾 java的核心库java.io提供了全面的IO接口.包括:文件读写.标准设备输出等.Java中I ...

  5. IO: BIO ? NIO ? AIO?

    IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. 一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSock ...

  6. Java IO(BIO, NIO, AIO) 总结

    文章转载自:JavaGuide 目录 BIO,NIO,AIO 总结 同步与异步 阻塞和非阻塞 1. BIO (Blocking I/O) 1.1 传统 BIO 1.2 伪异步 IO 1.3 代码示例 ...

  7. java io bio nio aio 详解

    BIO.NIO.AIO的区别: BIO就是基于Thread per Request的传统server/client实现模式, NIO通常采用Reactor模式, AIO通常采用Proactor模式, ...

  8. java io bio nio面试题_漫画:一文学会面试中常问的 IO 问题!

    原标题:漫画:一文学会面试中常问的 IO 问题! 作者 | 漫话编程 责编 | 伍杏玲 本文经授权转载自漫话编程(ID:mhcoding) 周末午后,在家里面进行电话面试,我问了面试者几个关于IO的问 ...

  9. Java的IO:BIO | NIO | AIO

    原文: http://my.oschina.net/bluesky0leon/blog/132361 BIO | NIO | AIO,本身的描述都是在Java语言的基础上的.而描述IO,我们需要从两个 ...

  10. java io流区别_Java中IO流的分类和BIO,NIO,AIO的区别

    到底什么是IO 我们常说的IO,指的是文件的输入和输出,但是在操作系统层面是如何定义IO的呢?到底什么样的过程可以叫做是一次IO呢? 拿一次磁盘文件读取为例,我们要读取的文件是存储在磁盘上的,我们的目 ...

最新文章

  1. mysql 左连接 去重复,MySQL删除左连接,3个表上的重复列
  2. 计算机指令格式哪几部分组成,计算机的指令格式,通常是由()两部分组成。 - 百科题库网...
  3. LeetCode 329. 矩阵中的最长递增路径(记忆化递归)
  4. 博士生是学生还是科研工作者?
  5. 辅助排序和Mapreduce整体流程
  6. 一幅漫画揭示了项目研发过程中存在的问题,太形象了
  7. 【JAVA】Java中goto语句的简介与使用(java 如何跳出内嵌多层循环的方法)
  8. linux创建云主机内存不足,云主机DC2 Linux系统CPU与内存占用率高导致无法登录
  9. UINavigationController与UITabbarController的样式
  10. 大学英语综合教程三 Unit 1至Unit 8 课文内容英译中 中英翻译
  11. 三目运算符 c语言求最小值,三目运算符
  12. 为什么微信显示这个android设备,微信显示安卓手机型号在哪设置
  13. 25.有5个人做在一起, 问第五个人多少岁? 他说比第四个人大2岁. 问第四个人岁数, 他说比第是三个人大2岁. 问第三个人, 又说比第二人大两岁. 问第二个人, 说比第一个人大两岁. 最后问第一个人
  14. 微信/QQ域名防封防拦截360不报毒任意链接跳转源码
  15. qt Redis使用
  16. AI上推荐 之 AFM与DIN模型(当推荐系统遇上了注意力机制)
  17. stm32中UART和USART的区别
  18. 自己动手做sidebar
  19. 笨鸟的平凡之路-简单理解什么是_consumers_offsets
  20. Xilinx下载电缆找不到,WARNING:iMPACT:923 - Can not find cable, check cable setup

热门文章

  1. 7-105 sdut-C语言实验——三个数排序7-106 sdut-C语言实验——模拟计算器7-107 sdut-C语言实验——找中间数
  2. hr2000 光谱Matlab,HR2000+光纤光谱仪
  3. 双手作业分析的作用是什么?为什么要做双手作业分析?
  4. 华为鸿蒙os 新闻,华为P50无限延期,谁来组成华为鸿蒙OS“头部”?
  5. 用简单的lnmp实现的论坛搭建
  6. JavaScript定时器-限时秒杀
  7. 论文笔记--GMAN: A Graph Multi-Attention Network for Traffic Prediction
  8. 微信公众平台如何配置业务域名
  9. js qs序列化数据 npmi qs --save
  10. 【转】高清混合矩阵应用于佛山市政府大礼堂会议系统解决方案