- 浏览: 233338 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
tonyyan:
谢谢分享!
Kafka 监控 -
dtyu100:
反手就是一个赞,这相当于是官网druid.io的中文版本,很厉 ...
Druid 大数据分析之快速应用(单机模式) -
sqy:
2018-04-12T01:30:27,527 ERROR [ ...
Druid 大数据分析之快速应用(单机模式) -
wangyudong:
学习了,不错的Spring boot实例,参考着很快写出了RE ...
Spring boot 入门实例 -
string2020:
servlet4规范出来了,求翻译
Java Servlet3.1规范
传统IO 写道
网络传输方式问题:传统的RPC框架或者基于RMI等方式的远程服务(过程)调用采用了同步阻塞IO,当客户端的并发压力或者网络时延增大之后,同步阻塞IO会由于频繁的wait导致IO线程经常性的阻塞,由于线程无法高效的工作,IO处理能力自然下降。下面,我们通过BIO通信模型图看下BIO通信的弊端:
采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接,接收到客户端连接之后为客户端连接创建一个新的线程处理请求消息,处理完成之后,返回应答消息给客户端,线程销毁,这就是典型的一请求一应答模型。该架构最大的问题就是不具备弹性伸缩能力,当并发访问量增加后,服务端的线程个数和并发访问数成线性正比,由于线程是JAVA虚拟机非常宝贵的系统资源,当线程数膨胀之后,系统的性能急剧下降,随着并发量的继续增加,可能会发生句柄溢出、线程堆栈溢出等问题,并导致服务器最终宕机。
NIO 写道
在IO编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者IO多路复用技术进行处理。IO多路复用技术通过把多个IO的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O多路复用的最大优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降低了系统的维护工作量,节省了系统资源。
JDK1.4提供了对非阻塞IO(NIO)的支持,JDK1.5_update10版本使用epoll替代了传统的select/poll,极大的提升了NIO通信的性能。
JAVA NIO实现服务端与客户端简单数据传输
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; /** * 服务端 */ public class SocketServer { /** * 服务器默认绑定端口 */ public static final int DEFAULT_PORT = 9999; /** * 选择器 */ public Selector selector; public SocketServer(String ip, int port) { ServerSocketChannel ssc = null; try { int _port = DEFAULT_PORT; if (port > 0) _port = port; /* 获取通道 */ ssc = ServerSocketChannel.open(); /* 配置非阻塞 */ ssc.configureBlocking(false); /** * 配置绑定端口 ServerSocketChannel没有bind()方法, * 因此有必要取出对等的ServerSocket并使用它来绑定到一 * 个端口以开始监听连接 */ ssc.socket().bind(new InetSocketAddress(ip, _port)); /* 获取选择器 */ this.selector = Selector.open(); /* 将通道注册到选择器 */ ssc.register(this.selector, SelectionKey.OP_ACCEPT); }catch(ClosedChannelException e1){ System.out.println("关闭的通道,无法注册到选择器"); e1.printStackTrace(); } catch (IOException e2) { try { if(ssc != null) ssc.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("服务器绑定端口冲突"); e2.printStackTrace(); } } /** * 轮询选择器 * @throws Exception */ public void pollSelect() throws Exception { /* (阻塞)轮询选择器,直到有事件 */ while (this.selector.select()>0) { /* 获取事件通知列表 */ Iterator<SelectionKey> it = this.selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey selectKey = it.next(); it.remove(); try { process(selectKey); } catch (Exception e) { e.printStackTrace(); continue; } } } } /** * 事件处理 * @param selectKey */ public void process(SelectionKey selectKey) throws Exception{ if (selectKey.isAcceptable()) { /* 客户端连接事件 */ accept(selectKey); } else if (selectKey.isReadable()) { /* 可读事件 */ read(selectKey); } } /** * 连接事件 * @param selectKey */ public void accept(SelectionKey selectKey) throws Exception { ServerSocketChannel ssc = null; try { ssc = (ServerSocketChannel) selectKey .channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); /* 发送信息 */ sc.write(ByteBuffer.wrap(new String("Hello World!") .getBytes())); /* 注册读事件 */ sc.register(this.selector, SelectionKey.OP_READ); } catch (ClosedChannelException e) { if(ssc!=null) ssc.close(); throw new IOException("关闭的通道,无法注册到选择器"); } catch (IOException e) { if(ssc!=null) ssc.close(); throw new IOException("连接服务或配置失败!"); } } /** * 可读事件 * @param selectKey */ public void read(SelectionKey selectKey) throws Exception{ SocketChannel channel = null; try { // 服务器可读取消息:得到事件发生的Socket通道 channel = (SocketChannel) selectKey.channel(); // 创建读取的缓冲区 ByteBuffer buffer = ByteBuffer.allocate(100); channel.read(buffer); byte[] data = buffer.array(); String msg = new String(data).trim(); System.out.println("客户端:" + msg); // ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes()); // 将消息回送给客户端 // channel.write(outBuffer); } catch (Exception e) { if(channel != null) channel.close(); throw new Exception("客户端将通道关闭,无法从通道读入缓冲或将缓冲数据写回通道!"); } } public static void main(String[] args) { SocketServer ss = null; try { ss = new SocketServer("localhost", 9999); ss.pollSelect(); } catch (Exception e) { e.printStackTrace(); } } }
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Iterator; /** * 客户端 */ public class SocketClient { public Selector selector; public SocketClient(String ip, int port){ SocketChannel channel = null; try { //channel = SocketChannel.open(new InetSocketAddress(ip,port)); channel = SocketChannel.open(); // 设置通道为非阻塞 channel.configureBlocking(false); // 获得一个通道管理器 this.selector = Selector.open(); // 客户端连接服务器,其实方法执行并没有实现连接 channel.connect(new InetSocketAddress(ip, port)); /**while(!channel.finishConnect()){ System.out.println("尝试连接...."); }*/ // 注册连接事件。 channel.register(this.selector, SelectionKey.OP_CONNECT); } catch(ClosedChannelException e1){ System.out.println("关闭的通道,无法注册到选择器"); e1.printStackTrace(); } catch (IOException e2) { System.out.println("连接异常!"); try { if(channel != null) channel.close(); } catch (IOException e) { e.printStackTrace(); } e2.printStackTrace(); } } /** * 轮询选择器 * @throws IOException */ public void pollSelect() throws Exception { /* (阻塞)轮询选择器,直到有事件 */ while ( this.selector.select() > 0 ) { /* 获取事件通知列表 */ Iterator<SelectionKey> ite = this.selector.selectedKeys().iterator(); while (ite.hasNext()) { SelectionKey selectKey = (SelectionKey) ite.next(); // 删除已选的key,以防重复处理 ite.remove(); process(selectKey); } } } /** * 处理事件 * @param selectKey */ public void process(SelectionKey selectKey) throws Exception{ if (selectKey.isConnectable()) { connect(selectKey); } else if (selectKey.isReadable()) { read(selectKey); } } /** * 连接事件 * @param selectKey * @throws Exception */ public void connect(SelectionKey selectKey) throws Exception{ try { SocketChannel channel = (SocketChannel) selectKey .channel(); /* 如果正在连接,则完成连接 */ if(channel.isConnectionPending()){ /** * connect()方法尚未被调用,调用finishConnect()方法, * 那么将产生NoConnectionPendingException */ channel.finishConnect(); } /** * 在非阻塞模式下调用connect()方法之后,SocketChannel又被切换回了阻塞模式;那么如果 * 有必要的话,调用线程会阻塞直到连接建立完成,finishConnect()方法接着就会返回true * 值。 */ /* 设置成非阻塞 */ channel.configureBlocking(false); /* 给服务端发送信息 */ channel.write(ByteBuffer.wrap(new String("编号001客户端连接成功!").getBytes())); /* 注册读事件 */ channel.register(this.selector, SelectionKey.OP_READ); } catch (ClosedChannelException e) { throw new IOException("关闭的通道,无法注册到选择器"); } catch (IOException e) { throw new IOException("连接服务或配置失败!"); } } /** * 读事件 * @param selectKey * @throws Exception */ public void read(SelectionKey selectKey) throws Exception{ try { // 服务器可读通道 SocketChannel channel = (SocketChannel) selectKey.channel(); // 创建读取的缓冲区 ByteBuffer buffer = ByteBuffer.allocate(100); channel.read(buffer); byte[] data = buffer.array(); String msg = new String(data).trim(); System.out.println(msg); ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes()); // 将消息回送给服务端 //channel.write(outBuffer); } catch (Exception e) { throw new IOException("服务端将通道关闭,无法从通道读入缓冲或将缓冲数据写回通道!"); } } public static void main(String[] args) { SocketClient sc = null; try { sc = new SocketClient("localhost", 9999); sc. pollSelect(); } catch (Exception e) { e.printStackTrace(); } } }
发表评论
-
数据接入ElasticSearch方式培训PPT
2018-01-28 11:53 1902写道 数据接入ElasticSearch几种方式总结,涉及 ... -
Apache ftp tools 图片下载支持中文
2017-12-05 23:55 1251写道 Apache Commom net:1) 递归pat ... -
FtpURLConnection 图片下载编码问题
2017-12-05 23:13 860写道 问题:1)Web项目中下载图片,存在下载不全,丢失部 ... -
Kafka 监控
2017-11-18 00:31 5777背景概述 写道 kafka0.9及以前版本ka ... -
Spring Cloud之OAuth2
2017-07-08 12:04 11412备:附件中OAuth2 授权服务器实现源码及PPT 一 ... -
Spring Cloud之Configuration Server
2017-05-19 22:51 1504为什么用spring cloud config 写道 一 ... -
Java Servlet3.1规范
2016-11-25 20:33 1250目录 前言........................ ... -
JMX监控(MBean)
2016-11-23 22:16 4105一、引言 写道 随着企业 IT 规模的不断增长,IT 资 ... -
哈希表在JAVA中如何实现
2016-11-23 20:42 2920一、 复习一下基础知识 1. 截断低位与抹除高位 ... -
Spring boot 入门实例
2016-10-29 00:33 4881写道 Spring Boot是由Pivotal团队提供的全 ... -
Java计算两点经纬度距离及最短运行时间
2016-09-12 21:20 2600概述 经纬度在地图应用中常见,一般结合路网信息库, ... -
计算机软件开源技术、大数据技术等资源教程
2016-08-24 13:01 588基于时间序列化数据引擎排名,很多OLAP工具,根据自身业务 ... -
代码单元与代码点
2016-08-16 17:46 692代码单元与代码点 代码点指编码表(比如Unicode)中某 ... -
Java模块化解决方案
2016-08-15 00:19 4196网络上很多OSGi的文章上来就Activator实例, ... -
深入浅出ClassLoader
2016-08-13 17:06 751你真的了解ClassLoader吗? 这篇文章翻译自zer ... -
Generate axis server code from wsdl
2016-08-04 00:34 12541、为什么需要生成服 ... -
Spring DAO设计实战
2016-01-23 12:21 3266引用 提供不同数据源和方言实现智能分页,因Spring单例 ... -
JAVA NIO 之三
2016-01-17 00:35 1735引用 本节采用JDK1.5之后java.util.con ... -
JAVA NIO 之二
2016-01-14 00:35 1978引用 继上节利用JAVA NIO实现简单数据传,本节实现自定 ... -
JAVA压缩图片并打成ZIP
2016-01-06 13:48 7446引用 JAVA 获取网络图片或本地图片压缩后打成ZIP,但 ...
相关推荐
通道是NIO中的核心概念之一,它提供了从一个数据源(如文件、套接字)到另一个数据源的数据传输路径。Java NIO支持多种类型的通道,包括文件通道(FileChannel)、套接字通道(SocketChannel)和服务器套接字通道...
**NIO非阻塞模式**:相比之下,NIO采用了非阻塞模式,即当没有数据可读时,`read()`方法不会阻塞,而是立即返回。这意味着应用程序可以同时处理多个输入/输出操作,而不需要为每个操作分配一个独立的线程。这样的...
Java NIO(New IO)是Java 1.4版本引入的一个新API,全称为New Input/Output,是对传统IO(Old IO)的扩展。...对于从事Java后端开发或者网络编程的工程师来说,深入理解并熟练运用Java NIO是必备的技能之一。
1. **Channels**: Channel是NIO的核心组件之一,它提供了一种从一个数据源(如文件、套接字或缓冲区)到另一个数据源传输数据的方式。SocketChannel是用于网络通信的通道,可以用于客户端与服务器建立TCP连接。 2. ...
首先,我们要理解Java NIO的核心组件之一——流。在Java的IO体系中,流是数据传输的抽象,它代表了数据的流向,可以是输入流(InputStream)或输出流(OutputStream)。然而,NIO中的流与传统的IO流有所不同,它们...
它们提供了对缓冲区(Buffers)的读写操作,是NIO的核心组件之一。 2. **缓冲区(Buffers)**:在NIO中,所有I/O操作都是通过缓冲区进行的。缓冲区是一个可以容纳特定类型数据的容器,比如ByteBuffer、CharBuffer、...
Java NIO(New IO)是Java 1.4版本引入的一个新特性,它为Java程序提供了非阻塞I/O操作的能力,极大地提升了Java在处理网络通信和文件读写时的性能。NIO与传统的IO( Blocking IO)模型相比,最大的区别在于其非阻塞...
Java NIO(New IO,也称为Non-blocking IO)和传统的Java IO是Java编程语言中用于处理I/O操作的两种主要技术。随着互联网用户数量的激增,企业对应用程序的并发处理能力提出了更高的要求。为了解决传统Java IO模型在...
缓冲区是 NIO 的核心组件之一,用于存储数据。Java NIO 提供了多种缓冲区,每种缓冲区对应不同的数据类型: - **ByteBuffer**:用于存储 byte 类型的数据。 - **CharBuffer**:用于存储 char 类型的数据。 - **...
[第4节] JavaNIO流-通道1.flv [第5节] Java NIO流-通道2.flv [第6节] Java NIO流-socket通道操作.flv [第7节] Java NIO流-文件通道操作.flv [第8节] Java NIO流-选择器 .flv [第9节] Java NIO流-选择器操作.flv...
- **缓冲区(Buffers)**:NIO中的数据操作都在缓冲区上进行,这是NIO的主要特性之一,缓冲区提供了更高效的数据存取方式。 - **选择器(Selectors)**:选择器允许单个线程监视多个通道,当通道准备好进行读写...
### Java-NIO2教程知识点详解 #### I/O发展简史 - **JDK1.0-1.3**: 在此期间,Java的I/O模型主要依赖于...这只是Java NIO2中众多强大功能之一,通过这些新的API,开发人员可以更高效、简洁地处理文件系统相关的操作。