- 浏览: 211042 次
- 性别:
- 来自: 哈尔滨
文章分类
- 全部博客 (267)
- java.lang (8)
- 问题汇总 (21)
- 异常记录 (20)
- 功能实现 (19)
- 面试总结 (25)
- 技巧总结 (8)
- 常用代码 (4)
- 编程习惯 (3)
- 编码规则 (3)
- java.util (10)
- java.io (1)
- JavaWeb (9)
- MySQL (16)
- SVN (3)
- MyBatis (11)
- Velocity (7)
- 其他知识 (10)
- 人生哲理 (1)
- 人生故事 (1)
- 自我感悟 (1)
- shiro (3)
- 基础知识 (0)
- 问题总结 (1)
- Spring 标签 (1)
- Spring (3)
- 点滴生活 (1)
- DOS (1)
- CAS (4)
- Linux (9)
- Storm (6)
- Shell (1)
- regex (1)
- Collection (4)
- poi (1)
- 经典语句 (1)
- NIO (5)
- concurrent (14)
- RPC (1)
- zookeeper (3)
- 待整理 (2)
- Hadoop (9)
- RabbitMq (2)
- flume (1)
- hive (7)
- hbase (4)
- kafka (1)
- scala (1)
- GC (0)
- java.util.concurrent.atomic (1)
- java.lang.ref (6)
- JVM (2)
- algorithm (1)
- conception (1)
- java key word (1)
- sun.misc (1)
最新评论
一、代码总结
服务端
客户端
工具类
二、IO方式
三种方式,各有优缺点,使用时考虑具体的应用场景。
如:上传下载文件时,若并发量大,则不可以用NIO,因为是同步处理,就会出现等待。
服务端
package com.study.nio.day3; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; /** * NIO-ServerSocketChannel 服务端 */ public class NIOServerDemo { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // 1.创建服务端channel;设置非阻塞模式,默认为true;绑定端口,接收此端口发送的信息 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); serverSocketChannel.socket().bind(new InetSocketAddress(9999)); // 2.创建选择器;将通道注册到选择器上; // 已注册集合 Selector selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); // 3.服务器处于开通状态,等待客户端连接,并处理客户端的请求并响应客户端 while(true){ // 已可以接收请求的channel的数量 // 已就绪集合 int readyCount = selector.select(); if(readyCount > 0){ // 可以工作 Iterator iterator = selector.selectedKeys().iterator(); while(iterator.hasNext()){ SelectionKey selectionKey = (SelectionKey) iterator.next(); if(selectionKey.isAcceptable()){ ServerSocketChannel serverSocketChannelAccept = (ServerSocketChannel) selectionKey.channel(); SocketChannel socketChannel = serverSocketChannelAccept.accept(); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); }else if(selectionKey.isReadable()){ SocketChannel readableChannel = (SocketChannel) selectionKey.channel(); readableChannel.configureBlocking(false); String content = NIOUtil.read(readableChannel); System.out.println("服务端接收"+"客户端"+readableChannel.socket().getInetAddress().getHostAddress()+"发送的信息:"+content); }else if(selectionKey.isWritable()){ SocketChannel writeableChannel = (SocketChannel) selectionKey.channel(); writeableChannel.configureBlocking(false); String content = "服务端"+writeableChannel.socket().getInetAddress().getHostAddress()+"接收到客户端的信息" ; NIOUtil.write(writeableChannel, content); writeableChannel.register(selector, NIOUtil.cancel(selectionKey, SelectionKey.OP_WRITE)); } iterator.remove(); } } } } }
客户端
package com.study.nio.day3; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Iterator; public class NIOClientDemo { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); socketChannel.connect(new InetSocketAddress("127.0.0.1",9999)); Selector selector = Selector.open(); socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE | SelectionKey.OP_READ); while(true){ int readyCount = selector.select(); if(readyCount > 0){ Iterator iterator = selector.selectedKeys().iterator(); while(iterator.hasNext()){ SelectionKey selectionKey = (SelectionKey) iterator.next(); // 得到的channel即为注册的channel SocketChannel socketChannelKey = (SocketChannel) selectionKey.channel(); socketChannelKey.configureBlocking(false); if(selectionKey.isConnectable()){ // 完成连接 socketChannel.finishConnect(); }else if(selectionKey.isWritable()){ String content = "NIO LEARNING FINISH ! NIO 学习总结" ; NIOUtil.write(socketChannelKey, content); socketChannel.register(selector, NIOUtil.cancel(selectionKey, SelectionKey.OP_WRITE)); } else if(selectionKey.isReadable()){ String content = NIOUtil.read(socketChannelKey); System.out.println("客户端接收"+"服务端"+socketChannelKey.socket().getInetAddress().getHostAddress()+"响应的信息:"+content); } iterator.remove(); } } } } }
工具类
package com.study.nio.day3; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; /** * NIO工具类 * @description * 避免粘包问题,约定发送与接收数据格式为: * 写入:content.getBytes("utf-8").length+"\r\n"+content * 读取:以"\r\n"为分割,头部为数据长度,尾部为数据内容 * 注意read 和 writer方法都无法保证是否完整的读取或写出,需要循环检查 * while(byteBuffer.hasRemaining()) */ public class NIOUtil { private static final String DEFAULT_CODED_FORMAT = "UTF-8" ; public static String read(SocketChannel socketChannel) throws IOException{ int contentLength = readContentHead(socketChannel); return readContentTail(socketChannel, contentLength) ; } /** * 读取内容的头部信息 * @description * 处理逻辑: * 建立大小为1的缓冲区 * 每次读入一个字符 * 若不是以\r\n结尾,则继续读入 * 否则结束,此时读取的结果为number\r\n * @param socketChannel * @return * @throws IOException */ private static int readContentHead(SocketChannel socketChannel) throws IOException{ String contentHead = "" ; ByteBuffer temp = ByteBuffer.allocate(1); while(!contentHead.endsWith("\r\n")){ socketChannel.read(temp); contentHead += new String(temp.array(),DEFAULT_CODED_FORMAT); temp.clear(); } int contentLenth = Integer.valueOf(contentHead.substring(0, contentHead.length()-2)).intValue(); return contentLenth; } private static String readContentTail(SocketChannel socketChannel,int contentLength) throws IOException{ ByteBuffer byteBuffer = ByteBuffer.allocate(contentLength); while(byteBuffer.hasRemaining()){ socketChannel.read(byteBuffer); } return new String(byteBuffer.array(),DEFAULT_CODED_FORMAT); } /** * 写入数据 * @param socketChannel * @param content * @throws IOException */ public static void write(SocketChannel socketChannel ,String content) throws IOException{ StringBuffer sb = new StringBuffer(); sb.append(content.getBytes(DEFAULT_CODED_FORMAT).length+"").append("\r\n").append(content); ByteBuffer byteBuffer = ByteBuffer.wrap(sb.toString().getBytes(DEFAULT_CODED_FORMAT)); while(byteBuffer.hasRemaining()){ socketChannel.write(byteBuffer); } } /** * 取消某op * @param selecttionKey * @param op * @return */ public static int cancel(SelectionKey selecttionKey, int op){ int ops = selecttionKey.interestOps(); return ops & ~op ; } }
二、IO方式
- 阻塞/非阻塞:是从线程的角度来考虑的,考虑线程是不是被挂起的状态
- 同步/异步:是从逻辑执行的角度来考虑的,考虑程序在处理一段逻辑时可否并行处理另一端逻辑
- BIO -- jdk1.0 -- BlockingIO -- 同步阻塞式IO -- 面向流操作字节字符 -- 单向传输
- NIO -- jdk1.4 -- NonBlockingIO -- 同步非阻塞式IO -- 面向通道操作缓冲区 -- 双向传输
- AIO -- jdk1.7 -- AnsyncronizeIO -- 异步非阻塞式IO -- 大量的使用回调函数实现了异步IO操作
三种方式,各有优缺点,使用时考虑具体的应用场景。
如:上传下载文件时,若并发量大,则不可以用NIO,因为是同步处理,就会出现等待。
相关推荐
五、NIO源码分析 对于NIO的源码,我们可以深入研究`Selector`、`SelectionKey`、`SelectorProvider`等关键类的实现,理解其内部的工作原理。此外,还可以关注`java.nio.channels`包下的各种通道类,如`FileChannel`...
#### 五、作者简介 - **Greg Travis**:一位自由 Java 程序员和技术撰稿人,具有丰富的编程经验和广泛的兴趣领域。他是 Manning Publications 出版的《JDK 1.4 Tutorial》一书的作者,也是本教程的主要撰写者。 ##...
#### 五、案例分析 假设我们正在开发一个简单的聊天服务器,用户可以连接到服务器并通过服务器相互发送消息。在这种情况下,我们可以利用Selector来监听多个客户端连接上的读写事件。当一个客户端发送消息时,...
#### 五、Channel妙用 **1. Channel的分类** - **FileChannel**: 用于文件的读写操作。 - **SocketChannel**: 用于网络套接字的读写操作。 - **DatagramChannel**: 用于UDP数据报的读写操作。 **2. 使用Channel**...
### NIO陷阱与解读 #### 一、NIO概述及变迁 ...总结,NIO虽然带来了显著的性能提升,但也伴随着一系列挑战。开发者需充分了解其内部机制,并结合具体的应用场景选择合适的设计方案和技术栈,才能真正发挥出NIO的优势。
五、多路复用 多路复用是NIO类库中的一个核心概念,用于实现多个I/O操作的集中管理。多路复用可以看作是一个高效的I/O模式,用于提高I/O操作的性能。多路复用可以使用Selector机制来实现,Selector可以管理多个...
#### 五、总结 Java NIO是一种更为高效和灵活的I/O处理方式,它通过Buffer、Channel、Selector和SelectionKey等核心组件实现了并发的非阻塞型I/O能力。相比于传统的阻塞I/O模型,NIO能够显著提高处理大量并发连接的...
- **第五章:正则表达式** - 5.1 正则表达式基础 - 介绍了正则表达式的概念及其基本语法。 - 5.2 Java 正则表达式 API - 讲解了 Java 中用于处理正则表达式的 API。 - 5.3 字符串类中的正则表达式方法 - 展示...
#### 五、总结 通过对《Pro Java 7 NIO2》中Path类的学习,我们可以看到NIO.2 API为Java开发者提供了强大而灵活的文件系统操作工具。从简单的路径构建到复杂的文件属性访问,Path类及其相关API为Java程序提供了处理...
#### 五、总结 Netty是一个功能强大且高度可定制的网络编程框架。通过本教程,我们不仅了解了Netty的基础概念,还通过实际代码示例学习了如何使用Netty构建一个简单的服务器和客户端应用程序。这对于理解Netty的...
#### 五、高级特性 NIO还包括了一些高级特性,如非阻塞I/O、选择器(Selector)等,这些特性进一步增强了NIO的性能和灵活性。 - **非阻塞I/O**:允许用户在不等待的情况下继续执行其他任务,提高了程序的并发处理...
#### 五、非阻塞 IO 的使用 Java NIO 支持非阻塞模式,使得线程在等待 IO 操作时可以执行其他任务。 ```java SocketChannel channel = SocketChannel.open(new InetSocketAddress("localhost", 8080)); channel....
#### 五、高级特性 ##### 5.1 异步I/O - **实现机制**:通过使用AsynchronousFileChannel和CompletionHandler等类来实现。 - **示例代码**: ```java AsynchronousFileChannel fileChannel = ...