java实现io阻塞的代码_Java IO(2)阻塞式输入输出(BIO)

2023-10-30

在上文中《Java IO(1)基础知识——字节与字符》了解到了什么是字节和字符,主要是为了对Java IO中有关字节流和字符流有一个更好的了解。

本文所述的输出输出指的是Java中传统的IO,也就是阻塞式输入输出(Blocking I/O, BIO),在JDK1.4之后出现了新的输入输出API——NIO(New I/O或Non-blocking I/O),也就是同步非阻塞式输入输出,再到后面随着NIO的发展出现了新的异步非阻塞式的输入输出——AIO。

本文将对BIO,即阻塞式输入输出的字节流以及字符流做简要概述。 需要明确对于输出:InputStream、Reader表示输入,前者表示字节流,后者表示字符流;OutStream、Writer表示输出,前者表示字节流,后者表示字符流。

字节流(InputStream、OutputStream)

对于字节流的输入顶层类是InputStram、其输出对应的顶层类是OutputStream。

输入流(InputStream)

站在程序的角度,读取文件的动作称为输入,InputStream是一个抽象类,Java中IO的设计并不仅仅是只有InputStream类,因为存在许多输入流,例如网络、文件等,这些都能为程序提供数据源,而不同的数据源则通过不同的InputStream子类来接收。

ByteArrayInputStream——字节数组。

StringBufferInputStream——String对象,这个类年代久远已经被废除了,想要将String对象转换为流,推荐使用StringReader。

FileInputStream——从文件中读取信息,这个流是比较常用的类,因为通常情况下我们都是对文件进行读写操作,所以也会着重讨论这个类。

PipedInputStream——和PipedOutputStream配合使用实现“管道化”的概念。

FileterInputStream——这个类比较特殊,从名字上看叫做“过滤器输入流”,它是在输入流中为“装饰器”提供基类。

着重来看FileInputStream类,如何从文件中读取信息。

FileInputStream 一共有3个构造方法:

InputStream in = new FileInputStream(“/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json”); //直接传递文件路径字符串,在这个构造函数中会为路径中的文件创建File对象。

InputStream in = new FileInputStream(new File(“/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json””)); //传递File类型的对象,也就是我们自己为路径中的文件构造为File文件类型。

InputStream in = new FileInputStream(new FileDescriptor()); //第三个构造方法传递的是“文件描述符”对象,通过文件描述符来定位文件,如果比较了解Linux和C的话应该是对“文件描述符”这个概念有所耳闻,在许多C源码中就时常出现“fd”这个变量,其表示的就是文件描述符,就是用于定位文件。这一个在Java日常的应用开发中不常用,用到它的地方其实就是System.out.println的封装。暂时可以忽略。

其实深入到FileInputStream这个对象的源码可以发现,大部分核心的源码都是native方法,之所以只用nativa方法是因为本地方法速度快。

1 File file = new File("/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json");2 InputStream in = newFileInputStream(file);3 byte[] b = new byte[64];4 in.read(b);5 System.out.println(new String(b));

这段代码是读取本地文件获取文件中的信息,其中read方法关键,FileInputStream中一共有3个read重载方法:

public int read() //返回读取的字节,FileInputStream是按照字节流的方式读取,使用该方法将一次读取一个字节并返回该字节。该方法中会调用private native int read0()本地方法。

public int read(byte b[]) //将读取的字节全部放到字节数组b中,这个字节数组b是我们提前定义好的,用于存放读取文件的字节表示,返回一共读取的字(1个字母表示1个字,1中文通常则是3个字)。该方法会调用private native int readBytes(byte b[], int off, int len)本地方法。

read(byte b[], int off, int len) //读取数据的开始处以及待存放字节数组的长度,基本同上,返回一共读取的字符(1个字母表示1个字符,1中文通常占用3个字节也就是3个字符)。该方法会调用private native int readBytes(byte b[], int off, int len)本地方法。

这基本上就构成了通过FileInputStream字节流读取文件的API,到了这里应该会有一个疑问,那就是读取出来的字节放到我们定义的字节数组中,而这个数组有需要在初始化时给定大小,那此时是如何知道待读取的文件大小呢?上面定义的64个字节大小的数组,如果待读取的文件有128字节甚至更大呢?就好像上面的例子,如果之定义1个字节大小,那么最后只会输出文件中的第1个字节。但如果定义64个字节大小的字节数组,那又显得比较浪费。

输出流(OutputStream)

同样是站在程序的角度,写入文件的操作称为输出。和InputStream类比,它也有许多实现类,在这里不再一一举出,着重来看FileOutputStream输出到本地文件的类。如果文件不存在则创建。

1 OutputStream out = new FileOutputStream("/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json");2 String str = "this is data";3 out.write(str.getBytes()); //由于是以字节流的方式输出,自然也是需要将输出的内容转换为字节。

FileOutputStream类的构造方法一共有5个:主要是分为“文件地址”、“是否以追加方式写入”、“文件描述符”。

OutputStream out = new FileOutputStream(“/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json”); //直接传递文件路径字符串,在构造方法中会将其构造为一个File对象,如果文件不存在则会新建文件,默认将覆盖文件的内容进行写入。因为它实际上是调用FileInputStream(File, boolean)构造方法。

OutputStream out = new FileOutputStream(new File(“/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json””)) //传递File对象,默认将覆盖文件的内容进行写入。实际还是调用FileInputStream(File, boolean)。

OutputStream out = new FileOutputStream(“/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json”, true); //第一个参数如第一点所述,第二个参数则表示以追加的方式写入。

OutputStream out = new FileOutputStream(new File(“/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json””), true) //向上参考

OutputStream out = new FileOutputStream (new FileDescriptor()); //第三个构造方法传递的是“文件描述符”对象,不需要过多的关注这个构造方法,因为实在能用的地方不多。

对于文件输出的核心API是write方法,对应文件输入的read方法。既然read能单个读取,那么write也有单个写入,其重载方法一共有3个。

public void write(int b); //写入单个字节,该方法会调用private native write(b, append)这个方法是私有且本地的,至于第二个append的参数则是表示是否追加写入文件,这里的参数是在构造方法中定义的,默认不追加写入而是以覆盖的方式写入。

public void write(byte b[]); //写入字节,这里传递转换后的字节数组,通常我们是需要写入一个字符串,而这里调用String.valueOf将其转换为字符数组。此方法会调用private native void writeBytes(byte b[], int off, int len, boolean append),和写入的类似,第二个参数表示字节数组从哪个地方开始写入,len表示写入多少,最后一个还是表示是否是追加写入。

public void write(byte b[], int off, int len); //分析见上 这是对OutputStream的其中一个实现类做的简要讲述,API也较为简单,类比很好掌握。

字符流(Reader、Writer)

输入流(Reader)

对于字符流的文件读取方式可以不用像字节流那样,读取出来是一个字节,想要输出显示这个字节则需要将这个字节转换为字符。字符流读取出来的文件则直接就是字符,不需要再重新转化。Reader和InputStream类似,也是一个抽象类,它也有不少的实现,其主要实现如下。

CharArrayReader

StringReader

InputStreamReader——这个类略有不同,这个类是字节流和字符流之间的桥梁,它能将字节流转换为字符流,相对比于“FileInputStream”,字节流的本地文件读取实际上是InputStreamReader的子类——FileReader

PipedReader

FilterReader

对比字符流的FileInputStream类,此处使用FileReader。和FileInputStream类似它同样有3个构造方法:

Reader reader = new FileReader(/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json”); //直接传递文件路径字符串,在这个构造函数中会为路径中的文件创建File对象。

Reader reader = new FileReader(new File(“/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json””)); //传递File类型的对象,也就是我们自己为路径中的文件构造为File文件类型。

Reader reader = new FileReader(new FileDescriptor()); //第三个构造方法传递的是“文件描述符”对象,通过文件描述符来定位文件,如果比较了解Linux和C的话应该是对“文件描述符”这个概念有所耳闻,在许多C源码中就时常出现“fd”这个变量,其表示的就是文件描述符,就是用于定位文件,暂时对它可以忽略。

可以看到它的API操作几乎和FileInputStream如出一辙,唯一不同的是,它定义的是字符数组而不是字节数组。

1 Reader reader = new FileReader("/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json");2 char[] c = new char[64];3 reader.read(c);4 System.out.println(String.valueOf(c));

同字节输入流FileInputStream类似,它的读取API也是read,并且它也有3个重载方法。如果还能记得FileInputStream的3个read重载方法,那么这里也不难猜出FileReader的3个read重载方法分别是:读取一个字符;读取所有字符;读取范围内的字符。实际上进入FileReader类后可以发现在FileReader类中并没有read方法,因为它继承自InputStreamReader,最后发现实际上FileReader#read调用的是父类InputputStreamReader#read方法,而且和字节流的read使用native本地方法略有不同,InputputStreamReader并没有采用native方法,而是使用了一个叫做StreamDecoder类,这个类源于sun包,并没有源代码,不过还是可以带着好奇心来一看反编译后的结果。

//InputputStreamReader#read

public int read(char cbuf[], int offset, int length) throwsIOException {return sd.read(cbuf, offset, length); //调用的StreamDecoder#read方法

}

对于使用FileReader#read方法调用的则是它的父类InputStreamReader#read,其实我认为可以这么理解:基于字符流的输入输出实际上是我们人为对它进行了转换,数据在网络中的传输实际还是以二进制流的方式,或者说是字节的方式,为了我们方便阅读,在传输到达时人为地将其转换为了字符的形式。所以即使这里是使用的FileReader以字符流的方式输入,但实际上它使用了字节-字符之间的桥梁——InputStreamReader类。也就是说StreamDecoder类很就是字节-字符转换的核心类。关于StreamDecoder类确实涉及比较复杂,Reader字符流本身也比字节流要复杂不少。这个地方的源码暂时还未深入了解。

输出流(Writer)

和字节输出流以及字符输入流之间的对比Writer也有很多实现类,我们找到有关本地文件写入的类——FileWriter,同样发现它继承自OutputStreamWriter,这个类是Writer的字节子类和InputStreamReader类似是字节流和字符流转换的桥梁。

有了上面的例子,这里不再逐个叙述它的构造方法以及write重载方法,有一个需要关注的地方就是它的flush方法。

1 Writer writer = new FileWriter("/Users/yulinfeng/Documents/Coding/Idea/maveneg/src/main/java/bio/test.json");2 String str = "hello";3 writer.write(str);4 writer.flush();

上面的代码中如果不调用flush方法,字符串将不会写入到文件中。这是因为在写文件时,Java会将数据先存入缓存区,缓存区满后再一次写入到文件中,在这里“hello”并没有占满缓存,故需要在调用write方法后再调用flush方法防止在缓存区中的数据没有及时写入文件。

不过这里有一个令我比较疑惑的是,在使用字节流输出只含1个字符到文件时,并没有使用flush也会将数据写到文件;而在字符流中则像上面的那种情况如果不使用flush则数据不会写入文件。答案确实是使用字节流输出数据到文件时,不需要使用flush,因为调用FileInputStream并没有重写flush方法,而是直接调用了父类OutputStream的falush方法,而OutputStream#flush方法里什么都没有,就是一个空方法;而使用FileWriter中虽然也并未实现flush方法,但在其父类OutputStreamWriter却实现了Writer的flush方法,因为在Writer类中flush方法是一个抽象方法必须实现。这里实际又会有一个疑问,为什么字符流不需要缓存,而字节流需要呢?其实就是因为对于字节流来说,是直接操作文件流,可以理解为“端到端”,而对于字符流来说中间多了一次转换为字符在“端到端”的中间利用了缓存(内存)将字符存放在了缓存中。所以在实际开发中利用字节流的方式输入输出相对更多。

小结

上面说了这么多,看似并没有多少干货,大多是关于这几个流的使用方法,如果仔细看下来会发现最大的干货在于最后的flush疑问。这实际上能揭开关于“字节流”和“字符流”之间的区别。 在重复一次,尽管字节流中有flush方法,但是flush在字节流FileOutputStream并没用,JDK源码能说明一切,因为FileOutputStream调用的flush方法根本就是一个空实现。然而在字符流中那就可得注意了,在FileReader调用了write方法后记住调用flush方法,清空缓存写入文件。 这个问题基本就能解释字节流和字符流之间的区别了,字节流直接操作文件,字符流虽然最后的呈现以及写入是字符,但其最终还是以字节在传输,字节到字符的转换是在内存中完成的,这也就是字符流用到了缓存的原因。其实想想就可以知道,对于两者哪个更好,字节流更常用,因为它直接操作文件读取写入字节并且不限于文本,可以是音乐、图片、视频,而字符流主要是针对纯文本文件,况且它还要转换一次,效率恐怕就没有字节来得那么快了,故一般就是直接使用字节流——InputStream和OutputStream操作文件。

什么是(同步)阻塞式输入输出(Blocking I/O)

这一部分的内容将解释本文的另一主题——阻塞式输出输出。

首先需要了解何为“阻塞”。如果对显示锁Lock有所了解的话,应该是会知道它的两个方法一个是阻塞式获取锁——lock,直到成功地获取所后才返回;另一个是非阻塞式获取锁——tryLock,它首先尝试获取锁,成功获取所则成功返回,未能获取锁也会立即返回,并不会一直等在这里获取锁。相对于阻塞式的IO也是类似,阻塞式IO也会一直等待数据的读取和写入直到完成;而对应的非阻塞式IO则不会这样做,它会立即返回,不管是完成或未完成。

再举个例子,在现实生活中你去买烟,老板说等下我去仓库里拿,你就一直在那里等老板从仓库里拿烟,这个时候你啥也不做就干等着,这就是阻塞;对于非阻塞,你还是在买烟,你还是在等老板给你拿烟,不过此时你可以玩玩手机,时不时问下老板好了没有。

上面的例子都是在“同步”条件下的阻塞与非阻塞。当然还有异步阻塞与非阻塞,这里暂不涉及异步相关,所以本文所述阻塞与非阻塞均是在同步状态下。

在此有必要了解什么是同步,通俗地说就是你进行下一步动作需要依赖上一步的执行结果。有时在我们的应用程序中,读取文件并不是下一步所必需的,也就是说这是两个不相干的逻辑,此时如果采用同步的手段去读取文件,读完过后再做另外的逻辑显然这个时间就被浪费了,通常情况下采取的措施是——伪异步,单独创建一个线程执行读取文件的操作,代码形如以下所示:

1 new Thread(newRunnable() {2 @Override3 public voidrun() {4 readFile();5 }6 }).start();7 doSomething();8 //lamda表达式则更加简单:9 //new Thread(() -> readFile()).start();10 //doSomething();

脱离场景谈同步阻塞式的传统IO显得很无力也不好理解,下面将结合Socket网络编程再次试着进一步理解“同步阻塞式IO”。

以Java中使用UDP进行数据通信为例,服务器端在创建一个socket后会调用其receive等待客户端数据的到来,而DatagramSocket#receive就是阻塞地等待客户端数据,如果数据一直不来,它将会一直“卡”在这个方法的调用处,也就是程序此时被阻塞挂起,程序无法继续执行。

1 //同步阻塞式,服务器端接收数据

2 DatagramPacket request = new DatagramPacket(new byte[1024], 1024);3 socket.receive(request);4 processData(new String(request.getData()));

试想以上代码,客户端发来的第1条、第2条……这些数据并无直接联系,它们只需要交给服务器端处理即可,但此时服务器端是同步阻塞式的获取数据并进行处理,在第1条数据未处理完时,第2条数据就必须等待,通常地做法就是上面提到的采用伪异步的方式对接收到的数据进行处理。

1 //(伪)异步阻塞式,服务器端接收数据

2 DatagramPacket request = new DatagramPacket(new byte[1024], 1024);3 socket.receive(request);4 new Thread(() -> { //lamda表达式

5 try{6 processData(newString(request.getData()));7 } catch(InterruptedException e) {8 e.printStackTrace();9 }10 }).start();

上面代码服务端接收到数据后将新开启一个线程对数据进行处理(更好地方式是利用线程池来管理线程),尽管采用了“伪异步”的方式处理数据,但实际上这是针对的是客户端发送数据多,发送数据快时所做的改进措施,但如果客户端发送的数据少,发送数据慢,实际上上面的修改并无多大意义,因为此时的症结不在于对服务器端对数据接收与处理的快慢,而在于服务器端将会一直阻塞获取数据使得服务器端程序被挂起。所以问题还是回到了“阻塞”式IO上来,想要解决这个问题就需要使用到“非阻塞”式IO,这也是下节所讲内容。

这是一个能给程序员加buff的公众号

我的博客即将同步至腾讯云+社区,邀请大家一同入驻。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java实现io阻塞的代码_Java IO(2)阻塞式输入输出(BIO) 的相关文章

  • 2014年1月8日--1月15日(杂事太多,算10小时,剩4733小时)

    1月8日 上午开会 下午被授课 算1小时吧 1月9日 决定完成光线追踪算法 DEMO7 1和 DX11的TRIANGLE 并把挖掘机的改造定帧 以及SHADER接口
  • Python人脸识别

    OpenCV 简介 OpenCV 的全称是Open Source Computer Vision Library 是一个跨平台的计算机视觉库 OpenCV 是由英特尔公司发起并参与开发 以 BSD 许可证授权发行 可以在商业和研究领域中免费
  • USB-数据传输

    一 USB编码 反向不归零编码 NRZI 位填充 规则 数据为0 电平反转 数据为1 电平不翻转 当连续出现6个相同的1穿插一个0 目的是为了防止连续出现多个1导致的同步漂移 二 USB传输帧 帧是USB传输的时间单位 低速 全速设备固定为
  • innerHtml用法

    innerHtml用法 span span
  • mktemp命令的用法

    一 概述 Linux使用 tmp目录来存放不需要永久保留的文件 mktemp命令专门用来创建临时文件 并且其创建的临时文件是唯一的 shell会根据mktemp命令创建临时文件 但不会使用默认的umask值 管理权限的 它会将文件的读写权限
  • gps模块协议NMEA-0183的解析----android4.2下的gps hal层

    这些天调试了一款GPS模组 对GPS的数据格式协议NMEA 0183有了一些了解 现把这些天的心得体会记录下来 GPS 模块硬件介绍 国内的一款GPS模组 使用uart接口与主控进行通信 这款GPS模组只需要供电 使能就能够工作 不需要下载
  • 树莓派3B+安装Debian系统,并配置ssh登录

    Table of Contents 1 需要准备的材料 2 下载镜像文件 3 清除SD卡并烧写系统 4 打开ssh登录权限 5 查看树莓派的IP地址 6 通过putty登录树莓派 1 需要准备的材料 SD卡 树莓派 读卡器 网线 2 下载镜
  • CRM巨头败走中国,Salesforce中国区或将解散?

    关注ITValue 看企业级最新鲜 最价值报道 作者丨海阳 出品丨ToB行业头条 ID wwwqifu Salesforce或将退出中国市场 海外软件在华遭遇 水土不服 ITValue 8月3日 相关传言称 美国最大客户关系管理SaaS供应
  • Centos开启SSH服务

    本篇文章为转载 原作者文章地址 Centos7开启SSH服务 KinwingHU 博客园 cnblogs com 在虚拟机 Vmware Workstation 下 安装了CentOS7 现在想通过SSH工具连接虚拟机中的CentOS7 1
  • vue实现聊天框自动滚动

    需求 1 聊天数据实时更新渲染到页面 2 页面高度随聊天数据增加而增加 3 竖向滚动 4 当用户输入聊天内容或者接口返回聊天内容渲染在页面后 自动滚动到底部 5 提供点击事件操控滚动条上下翻动 环境依赖 vue vue cli 5 0 8
  • Java VisualVM无法更新或安装插件解决办法

    Java VisualVM是JDK中的一个工具 可以实时查看Java程序内存变化的情况 今天在更新或安装时有时会出现建立连接时的问题 提示找不到系统文件 出现这种问题是因为地址出现了问题 整了半天 发现是原来的地址已经发生了改变 解决方法
  • html5实现有道翻译文字播报语音,H5实现文字语音播报

    前言 搜了一堆百度 搜狗 有道的 没有一个能用的 只能投机取巧了 实现 获取播放路径 html
  • Python实现文件编码转换GB2312、GBK、UTF-8

    Python实现文件编码转换GB2312 GBK UTF 8 1 查看文件编码格式 import chardet filename flash c with open filename rb as f data f read encodin
  • [BugKu Web]ez_serialize

    本writeup已经在bugku开放 根据题意 显然是一道JAVA反序列化的题 关于JAVA反序列化漏洞的成因 参见博客https zhuanlan zhihu com p 422314689 此处只说明解题思路 重复开启场景已经没金币了
  • flex布局,子元素设置flex: 1和nowrap,内容长度超出盒子

    解决方法 子元素设置宽度即可 flex 1 width 0 或者 flex 1 min width 0
  • Springboot 项目启动出现 Mysql Lock wait timeout exceeded; try restarting transaction 错误

    一 查询 你的当前数据是否有 Sleep 的事务 执行 sql 检查 在你的项目停止或关闭后检查 show full PROCESSLIST 如果有执行 kill 杀掉 kill id kill 3009 二 查询是否存在挂起的锁 sele
  • pc虚拟服务器,基于虚拟服务器的分布式PC共享平台设计及实现

    摘要 随着云计算等技术的不断发展 C S架构的计算能力在慢慢地向服务器端倾斜 公有云 私有云等产品的出现 代表着人们访问应用程序时不再依赖于传统PC而是借助瘦客户机等连接网络的设备 本文旨在构建基于虚拟服务器的分布式PC共享平台 将桌面虚拟
  • 毕业设计-基于生成对抗网络的图像风格迁移

    目录 前言 课题背景和意义 实现技术思路 一 相关工作 二 基于生成对抗网络的风格迁移模型 三 实验与结果分析 四 总结 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备 一边要为
  • 计算机算法与程序设计 第一章 编程作业

    返回 所有测验 作业和考试都在2020年12月30日23点截止 请及时完成 编程作业题可以多次提交 取最高分作为本题成绩 依照学术诚信条款 我保证此作业是本人独立完成的 温馨提示 1 本次作业属于Online Judge题目 提交后由系统即

随机推荐

  • 解决Windows系统缺少comres.dll文件无法启动程序问题

    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题 如果是新手第一时间会认为是软件或游戏出错了 其实并不是这样 其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库 这时你可以下载这个comres
  • 类的静态成员变量初始化时间

    首先先搞明白 声明 定义 初始化 类的静态成员变量在类内声明 可以多次声明 类的静态成员必须在类外定义 定义就是给变量分配内存 初始化就是给一个变量赋初值 内置类型通常定义时默认初始化 类静态成员变量在main函数执行前完成初始化 有静态初
  • buck拓扑原理及仿真

    buck基本拓扑结构 开关管ON 电源向负载电阻提供电能 电感电流线性增大 变化率 变化量 开关管OFF 电感 电容中能量继续向负载电阻提供电能 电感电流线性减小 变化率 变化量 平衡状态时 由电感伏秒平衡得 推导得 理论电感电流在CCM
  • 快节奏多人在线游戏网络入门系列教程(2):客户端预测与服务器协调

    简介 在上一篇文章中 我们简单介绍了权威服务器的体系 客户端发送交互信息给服务器 服务器周期性的更新游戏状态 然后返回游戏状态给客户端 这个简单体系会导致用户发送命令时和屏幕渲染响应之间的延迟 产生延迟的原因是客户端发送命令给服务器 加上服
  • BIO/NIO/AIO

    IO模型 BIO BIO全称为 Blocking I O 是一种同步阻塞IO 最开始的网络通信就是BIO模型 服务端创建一个ServerSocket 客户端创建一个 Socket 去连接服务端 这样客户端与服务端便可以进行通信了 产生的问题
  • Mybatis中针对数据库日期JdbcType设置

    Mybatis中针对数据库日期JdbcType设置 在学习Mysql的时候 我们知道数据库类型有date datatime time类型 在用Mybatis进行插入数据的时候 我们实体一般都是直接指定java util Date类型 为了确
  • 机器学习中的相似性度量

    https www cnblogs com heaad archive 2011 03 08 1977733 html 1 欧氏距离 曼哈顿距离 切比雪夫距离 闵可夫斯基距离 标准化欧氏距离 马氏距离 夹角余弦 汉明距离 杰卡德距离 杰卡德
  • 菜鸟入门HTML

    标题HTML 一 1 单标签 一般单独完成某一功能的标签都为单标签 link 导入图片或css或其他资源 例 img src路径 插入一个图片到网页中 例 img src title 123 在这里插入图片描述 https img blog
  • 转:彻底搞定期货穿透式CTP API接入

    中信期货看穿式监管认证操作指南 CTP系统 https www citicsf com static download soft E4 B8 AD E4 BF A1 E6 9C 9F E8 B4 A7 E7 9C 8B E7 A9 BF E
  • NTSC和PAL制同步信号模拟输出

    NTSC和PAL制同步信号模拟输出 原由 由于我想输出一个NTSC制和PAL制的同步黑场 只需要输出同步信号 之后输出rgb信号给ADV 7123 后输出到显示屏 下面是我的心路历程和知识总结 一 了解NTSC和PAL PAL 电视标准 每
  • kinect2.0视角范围和距离远近

    本文章由cartzhang编写 转载请注明出处 所有权利保留 文章链接 http blog csdn net cartzhang article details 44588097 作者 cartzhang Kinect 摄像头范围介绍和玩家
  • 马踏棋盘求----全部解

    标题 运用栈和回溯法求马踏棋盘的全部解 回溯法的写法参考 数据结构 严蔚敏 的迷宫求解 感谢我的队友 汪汪汪 他与求一个解不同之处在于 当我们求到一个解之后 这个程序却会告诉计算机 啊 这不是我们想要的解 我们继续吧 于是 傻傻的计算机就信
  • D3D资源管理

    摘要 受管贴图 Managed textures 也就是我们通常所谓的 自动管理贴图 在DX6中首次被引入 经过一系列的改进和增强 在DX9中自动管理的资源类型增加到贴图 顶点缓冲 顶点索引缓冲 所有这些资源使用统一的公共接口 通过使用D3
  • 【图文分析】Java经典基础练习题(六):猴子吃桃子问题

    文章目录 一 具体题目 二 思路分析 逆向思维 三 代码 结果 代码 结果 四 彩蛋 一 具体题目 猴子第一天摘下若干个桃子 当即吃了一半 还不瘾 又多吃了一个 第二天 早上又将剩下的桃子吃掉一半 又多吃了一个 以后每天早上都吃了前一天剩下
  • Webpack4 配置 Externals

    Externals 配置项用来告诉 Webpack 要构建的代码中使用了哪些不用被打包的模块 也就是说这些模版是外部环境提供的 Webpack 在打包时可以忽略它们 1 有些 JavaScript 运行环境可能内置了一些全局变量或者模块 例
  • 新手小白学Java

    刚开始学习java的时候 可能是一头雾水 不知道从何学起 还有很多Java小白 在刚自学Java的时候玩命的学习 玩命的记住Java原理 天天早上五点起床背Java的一些英文词汇 然后遇见一些未知的困难 让自己打到癫狂状态 逐渐迷失自我放弃
  • 在开发板上挂载NFS

    网络文件系统 NFS Network File System 是一种将远程主机上的分区 目录 经网络挂载到本地系统的一种机制 通过对网络文件系统的支持 用户可以在本地系统上像操作本地分区一样来对远程主机的共享分区 目录 进行操作 在嵌入式L
  • 《动手学深度学习 Pytorch版》 4.8 数值稳定性和模型初始化

    4 8 1 梯度消失和梯度爆炸 整节理论 详见书本 梯度消失 matplotlib inline import torch from d2l import torch as d2l x torch arange 8 0 8 0 0 1 re
  • 安装完MySQL后,却没有密码,如何登录并修改密码?

    1 在终端输入sudo vim etc mysql mysql conf d mysqld cnf 2 在 mysqld 下方的skip external locking下面添加一行 skip grant tables 3 重启MySQL服
  • java实现io阻塞的代码_Java IO(2)阻塞式输入输出(BIO)

    在上文中 Java IO 1 基础知识 字节与字符 了解到了什么是字节和字符 主要是为了对Java IO中有关字节流和字符流有一个更好的了解 本文所述的输出输出指的是Java中传统的IO 也就是阻塞式输入输出 Blocking I O BI