xnio java_java基础篇---新I/O技术(NIO)

在JDK1.4以前,I/O输入输出处理,我们把它称为旧I/O处理,在JDK1.4开始,java提供了一系列改进的输入/输出新特性,这些功能被称为新I/O(NEW I/O),新添了许多用于处理输入/输出的类,这些类都被放在java.nio包及子包下,并且对原java.io包中的很多类以NIO为基础进行了改写,新添了满足新I/O的功能。

Java NIO和IO的主要区别

IO

NIO

面向流

面向缓冲

阻塞IO

非阻塞IO

选择器

面向缓冲(Buffer)

在整个Java的心I/O中,所以操作都是以缓冲区进行的,使操作的性能大大提高。

操作

在Buffer中存在一系列的状态变量,这状态变量随着写入或读取都可能会被概念,在缓冲区开元使用是三个值表示缓冲区的状态。

position:表示下个缓冲区读取或写入的操作指针,没向缓冲区中华写入数据的时候 此指针就会改变,指针永远放在写入的最后一个元素之后。即:如果写入了4个位置的数据,则posotion会指向第5个位置。

Limit:表示还有多少数据可以存储或读取,position<=limit

capacity:表示缓冲区的最大容量,limit<=capacity,此值在分配缓冲区时被设置。一般不改变。

创建缓冲区:

importjava.nio.IntBuffer ;public classIntBufferDemo{public static voidmain(String args[]){

IntBuffer buf= IntBuffer.allocate(10) ; //准备出10个大小的缓冲区

System.out.print("1、写入数据之前的position、limit和capacity:") ;

System.out.println("position = " + buf.position() + ",limit = " + buf.limit() + ",capacty = " +buf.capacity()) ;int temp[] = {5,7,9} ;//定义一个int数组

buf.put(3) ; //设置一个数据

buf.put(temp) ; //此时已经存放了四个记录

System.out.print("2、写入数据之后的position、limit和capacity:") ;

System.out.println("position = " + buf.position() + ",limit = " + buf.limit() + ",capacty = " +buf.capacity()) ;

buf.flip() ;//重设缓冲区//postion = 0 ,limit = 原本position

System.out.print("3、准备输出数据时的position、limit和capacity:") ;

System.out.println("position = " + buf.position() + ",limit = " + buf.limit() + ",capacty = " +buf.capacity()) ;

System.out.print("缓冲区中的内容:") ;while(buf.hasRemaining()){int x =buf.get() ;

System.out.print(x+ "、") ;

}

}

}

如果创建了缓冲区,则JVM可直接对其执行本机的IO操作

importjava.nio.ByteBuffer ;public classByteBufferDemo{public static voidmain(String args[]){

ByteBuffer buf= ByteBuffer.allocateDirect(10) ; //准备出10个大小的缓冲区

byte temp[] = {1,3,5,7,9} ; //设置内容

buf.put(temp) ; //设置一组内容

buf.flip() ;

System.out.print("主缓冲区中的内容:") ;while(buf.hasRemaining()){int x =buf.get() ;

System.out.print(x+ "、") ;

}

}

}

通道(Channel)

Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。

Java NIO的通道类似流,但又有些不同:

既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。

通道可以异步地读写。

通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。

正如上面所说,从通道读取数据到缓冲区,从缓冲区写入数据到通道。

15c42f9e5051a9556c44f02d41c8fecb.png

Channel的实现

这些是Java NIO中最重要的通道的实现:

FileChannel

DatagramChannel

SocketChannel

ServerSocketChannel

FileChannel 从文件中读写数据。

DatagramChannel 能通过UDP读写网络中的数据。

SocketChannel 能通过TCP读写网络中的数据。

ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

通过通道可以完成双向的输入和输出操作。在通道还有一种方式称为内存映射

几种读入的方式的比较

RandomAccessFile 较慢

FileInputStream 较慢

缓冲读取      速度较快

内存映射      速度最快

FileChannel内存映射实例

importjava.nio.ByteBuffer ;importjava.nio.MappedByteBuffer ;importjava.nio.channels.FileChannel ;importjava.io.File ;importjava.io.FileOutputStream ;importjava.io.FileInputStream ;public classFileChannelDemo03{public static void main(String args[]) throwsException{

File file= new File("d:" + File.separator + "oumyye.txt") ;

FileInputStream input= null;

input= newFileInputStream(file) ;

FileChannel fin= null ; //定义输入的通道

fin = input.getChannel() ; //得到输入的通道

MappedByteBuffer mbb = null;

mbb= fin.map(FileChannel.MapMode.READ_ONLY,0,file.length()) ;byte data[] = new byte[(int)file.length()] ; //开辟空间接收内容

int foot = 0;while(mbb.hasRemaining()){

data[foot++] = mbb.get() ; //读取数据

}

System.out.println(new String(data)) ; //输出内容

fin.close() ;

input.close() ;

}

}

操作以上代码的时候,执行的是写入操作则可能是非常危险的,因为仅仅只是改变数组中的单个元素这种简单的操作,就可能直接修改磁盘上的文件,因为修改数据与数据保存在磁盘上是一样的。

选择器(Selectors)

Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。这样,一个单独的线程可以管理多个channel,从而管理多个网络连接。

为什么使用Selector?

仅用单个线程来处理多个Channels的好处是,只需要更少的线程来处理通道。事实上,可以只用一个线程处理所有的通道。对于操作系统来说,线程之间上下文切换的开销很大,而且每个线程都要占用系统的一些资源(如内存)。因此,使用的线程越少越好。

但是,需要记住,现代的操作系统和CPU在多任务方面表现的越来越好,所以多线程的开销随着时间的推移,变得越来越小了。实际上,如果一个CPU有多个内核,不使用多任务可能是在浪费CPU能力。不管怎么说,关于那种设计的讨论应该放在另一篇不同的文章中。在这里,只要知道使用Selector能够处理多个通道就足够了。

要点

使用Selector可以构建一个非阻塞的网络服务。

在新IO实现网络程序需要依靠ServerSocketChannel类与SocketChannel

Selector实例

下面使用Selector完成一个简单的服务器的操作,服务器可以同时在多个端口进行监听,此服务器的主要功能是返回当前时间。

importjava.net.InetSocketAddress ;importjava.net.ServerSocket ;importjava.util.Set ;importjava.util.Iterator ;importjava.util.Date ;importjava.nio.channels.ServerSocketChannel ;importjava.nio.ByteBuffer ;importjava.nio.channels.SocketChannel ;importjava.nio.channels.Selector ;importjava.nio.channels.SelectionKey ;public classDateServer{public static void main(String args[]) throwsException {int ports[] = {8000,8001,8002,8003,8005,8006} ; //表示五个监听端口

Selector selector = Selector.open() ; //通过open()方法找到Selector

for(int i=0;i

ServerSocketChannel initSer= null;

initSer= ServerSocketChannel.open() ; //打开服务器的通道

initSer.configureBlocking(false) ; //服务器配置为非阻塞

ServerSocket initSock =initSer.socket() ;

InetSocketAddress address= null;

address= new InetSocketAddress(ports[i]) ; //实例化绑定地址

initSock.bind(address) ; //进行服务的绑定

initSer.register(selector,SelectionKey.OP_ACCEPT) ; //等待连接

System.out.println("服务器运行,在" + ports[i] + "端口监听。") ;

}//要接收全部生成的key,并通过连接进行判断是否获取客户端的输出

int keysAdd = 0;while((keysAdd=selector.select())>0){ //选择一组键,并且相应的通道已经准备就绪

Set selectedKeys = selector.selectedKeys() ;//取出全部生成的key

Iterator iter =selectedKeys.iterator() ;while(iter.hasNext()){

SelectionKey key= iter.next() ; //取出每一个key

if(key.isAcceptable()){

ServerSocketChannel server=(ServerSocketChannel)key.channel() ;

SocketChannel client= server.accept() ; //接收新连接

client.configureBlocking(false) ;//配置为非阻塞

ByteBuffer outBuf = ByteBuffer.allocateDirect(1024) ; // outBuf.put(("当前的时间为:" + new Date()).getBytes()) ; //向缓冲区中设置内容

outBuf.flip() ;

client.write(outBuf) ;//输出内容

client.close() ; //关闭

}

}

selectedKeys.clear() ;//清楚全部的key

}

}

}

服务器完成之后可以使用Telnet命令完成,这样就完成了一个一部的操作服务器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/245939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python函数返回none_Python 函数默认返回None的原因

Python 函数默认返回None是什么原因&#xff1f;定义的函数没有返回值&#xff0c;Python 解释器就会强行地默认给注入一段返回逻辑&#xff01;实际上 Python 中有很多行为都是隐性的。Python 有一项默认的做法&#xff0c;很多编程语言都没有&#xff0c;所有函数都会有一个返…

简易计算器 java_用Java做一个简易计算器,要用到哪些知识?

分析问题关键词&#xff1a;Java、计算器深夜无聊&#xff0c;暂且一答。计算器分两个步骤&#xff1a;计算 器篇一 「器」在编程中&#xff0c;我们可以把「器」理解为「GUI(图形界面)」&#xff0c;Java 语言描绘的图形界面有很多种类&#xff0c;比如 awt、swing、javaFX 等…

picturectrl控件中加载图片并显示_如何在EasyX窗体中显示图片

前提&#xff1a;图片必须是.jpg或.bmp格式的图片。(一)将保存在电脑桌面上的图片显示在EasyX窗体中&#xff0c;图片路径为&#xff1a;C:甥敳獲Administrator.USER-20190823VFDesktop锤头镰刀旗.jpg。(二)程序代码&#xff1a;#include#includeint main(){initgraph(500,300)…

estemplate 导入MySQL_[数据库]es~通过ElasticsearchTemplate进行聚合操作

[数据库]es~通过ElasticsearchTemplate进行聚合操作02020-08-24 17:00:38聚合操作&#xff0c;我们可以对数据进行分组的求和&#xff0c;求数&#xff0c;最大值&#xff0c;最小值&#xff0c;或者其它的自定义的统计功能&#xff0c;es对聚合有着不错的支持&#xff0c;需要…

iis mysql版本切换_MySQL+PHP配置 Windows系统IIS版(转)

1、下载MySQL下载地址&#xff1a;http://dev.mysql.com/downloads/mysql/5.1.html->Windows (x86, 32-bit), MSI Installer Essentials - Recommended(不包含文档)->No thanks, just start my download.(无需登录注册 直接下载)PHP下载地址&#xff1a;www.php.net->…

ping网关丢包_网络/摄像机丢包的原因分析

引文不少人在使用网络和监控摄像系统的时候都有遇到过数据丢包的情况&#xff0c;数据丢包的原因是多种多样的&#xff0c;以下就为大家介绍一下网络数据丢包的原因及摄像机丢包的原因。原因分析摄像机丢包的原因1&#xff1a;路由错误网络路径错误也会导致数据包不能到达目的主…

java aes 填充_Java中的Aes解密 – 填充问题

我更改了一些代码行,以保证大文件的加密.现在我遇到了问题,解密不起作用.我收到以下错误消息/异常&#xff1a;Error encrypting/decrypting fileat Algorithmus.Encryptor.doCrypto(Encryptor.java:71)at Algorithmus.Encryptor.decrypt(Encryptor.java:39)at GUI.MainWindow$…

plantuml语法_PlantUML实践 | 思维导图

❝思维导图又叫心智导图&#xff0c;用于表达发散性思维的图形工具。❞语法使用一些运算符(如&#xff1a;&#xff0c;-&#xff0c;*)来决定图形方向。相同运算符数量则在同一级。运算符数量越多&#xff0c;层级越深。支持内置前缀图标标记&#xff0c;如旗帜图标。示例star…

Java常用API例子_Java常用API及Math类

一、API的概述API——Application Programing Interface:应用程序编程接口&#xff0c;是java提供的一些预定义的函数&#xff1b;目的&#xff1a;基于API实现程序的快速编写&#xff0c;只需了解其作用&#xff0c;不用关注源代码。学习API的方法&#xff1a;先了解API的概况…

prometheus连续查询_Prometheus 不完全避坑指南

原文发表于 我的个人博客&#xff0c;同步发表到我的知乎专栏 Prometheus 是一个开源监控系统&#xff0c;它本身已经成为了云原生中指标监控的事实标准&#xff0c;几乎所有 k8s 的核心组件以及其它云原生系统都以 Prometheus 的指标格式输出自己的运行时监控信息。我在工作中…

java猜字母讲解_java_猜字母游戏

java猜字母游戏猜字母游戏&#xff1a;用户指定游戏难度(5、7、9)&#xff0c;程序生成随机不重复字母。用户猜错&#xff0c;提示用户对的字母数量和对的位置数量。import java.util.Scanner;public class GuessWord {public static void main(String[] args) {Scanner scanne…

list java removeif_java – removeIf()方法.从List中删除所有元素

我有一个用户列表,我想从我的列表中删除id为其实我这样做&#xff1a;[...]int pid1 1;int pid2 2;int pid3 3;Predicate personPredicate1 p-> p.getPid() pid1;Predicate personPredicate2 p-> p.getPid() pid2;Predicate personPredicate3 p-> p.getPid() …

服务器是什么系统_服务器自愈路由系统、单线以及BGP多线的区别是什么?

你是否了解服务器自愈路由系统呢&#xff1f;你是否了解服务器单线路呢&#xff1f;你是否了解服务器BGP多线路呢&#xff1f;你是否知道它们之间有什么区别呢&#xff1f;本文主要分为两大块来讲&#xff1a;1.分别简单的介绍下服务器的自愈路由系统、服务器单线路和服务器BGP…

java api管理工具_一个能快速写出实体类的Api文档管理工具

今天各种MVC框架满天飞&#xff0c;大大降低了编码的难度&#xff0c;写实体类就没有办法回避的一件事了&#xff0c;花大把的时间去做一些重复而且繁琐的工作&#xff0c;实在不是一个优秀程序员的作风&#xff0c;所以多次查找和尝试后&#xff0c;找到一个工具类网站——Api…

recyclerview 分组_Android使用RecyclerView实现跨列分组

效果图&#xff1a;需求分析&#xff1a;如上图所示&#xff0c;这是一个展示年级及学期的界面。年级分为三组高中、初中和小学。因学期太多若按一个一个控件的写既繁琐又不够优雅&#xff0c;所以我采用 RecyclerView配合分组来实现效果。注意&#xff1a;我这边是使用一个 Re…

rtmp服务器_nginx+windwos 搭建 rtmp 流媒体服务器

喜欢就关注我们吧&#xff01;“ 写此篇文章属于笔者在开发项目中&#xff0c;对项目开发架构的一种选型&#xff0c;目前正在探索阿里云的视频直播服务和nginx自行搭建流媒体服务器&#xff0c;希望能选择最优的一种方案&#xff0c;进行开发。”以下是使用nginx自行搭建rtmp流…

java rest风格传参_SpringMVC的REST风格的四种请求方式总结

一、 在HTTP 协议里面&#xff0c;四个表示操作方式的动词&#xff1a;GET、POST、PUT、DELETE。它们分别对应四种基本操作&#xff1a;1、GET 获 取资源2、POST 新建资源3、PUT 更新资源4、DELETE 删除资源二、REST&#xff1a;即 Representational State Transfer。(资源)表…

java语言编写进制转换_Java 3种方法实现进制转换

由其他进制转换为十进制比较简单&#xff0c;下面着重谈一谈十进制如何化为其他进制。1.使用Java带有的方法Integer&#xff0c;最简单粗暴了&#xff0c;代码如下//使用java提供的方法//但仅局限于比较常用的二进制、八进制、十六进制public static String trans1(int num, in…

r语言聚类分析_图说层次聚类分析原理和R语言实现

1、引言“物以类聚、人以群分”。但我们面对一群人或者一堆物的时候&#xff0c;我们都希望将他们分分类&#xff0c;分类之后&#xff0c;我们才能更加有针对性地采取措施&#xff0c;从而提高工作效率。如&#xff0c;我们将消费者分成若干类&#xff0c;有的是土豪、有的是工…

peewee创建mysql_python – peewee MySQL,如何创建包装SQL构建的ins的自定义字段类型?...

我想在peewee(通过MySQL)创建一个自定义UUID字段.在python中,我使用UUID作为一个六角形字符串,例如&#xff1a;uuid ’110e8400-e29b-11d4-a716-446655440000′但是我想将它存储在数据库中的BINARY(16)类型的列中以节省空间.MySQL内置了HEX()和UNHEX()方法,可以在字符串和二进…