Java NIO 必知必会(Example)
管道流:
Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。
package base.nio.threaddemo; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Pipe; /**
* @program: Lear-Java
* @description:
* @author: Mr.Dai
* @create: 2018-10-05 20:43
**/
public class ThreadSend { private Pipe pipe; private void init() throws Exception {
this.pipe = Pipe.open();
} class SendInner1 extends Thread { @Override
public void run() {
// 单向流 发送数据
try {
Pipe.SinkChannel sink = pipe.sink();
sink.configureBlocking(false); while (true) {
if (sink.isOpen()) {
sink.write(ByteBuffer.wrap("abcd".getBytes()));
}
Thread.sleep(1000);
}
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
} class ReverInner extends Thread {
@Override
public void run() {
try {
// 单向流 拿到数据
Pipe.SourceChannel source = pipe.source(); source.configureBlocking(false); while (true) {
if (source.isOpen()) {
ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.clear();
source.read(buffer);
// 这里必须去掉 trim
if(new String(buffer.array()).trim().equals("")){
continue;
}
System.out.println(new String(buffer.array()).trim());
}
Thread.sleep(1000);
}
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) throws Exception {
ThreadSend send = new ThreadSend(); send.init(); SendInner1 sendI = send.new SendInner1(); ReverInner revI = send.new ReverInner(); sendI.start();
revI.start();
} }
套接字通道流
非阻塞模式
ServerSocketChannel可以设置成非阻塞模式。在非阻塞模式下,accept() 方法会立刻返回,如果还没有新进来的连接,返回的将是null。 因此,需要检查返回的SocketChannel是否是null。如:
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(9999));
serverSocketChannel.configureBlocking(false); 6 while(true){
SocketChannel socketChannel =
serverSocketChannel.accept(); if(socketChannel != null){
//do something with socketChannel...
}
}
server:
package base.nio.chatdemo; import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set; /**
* @program: Lear-Java
* @description: Nio 聊天服务端
* @author: Mr.Dai
* @create: 2018-10-05 16:31
**/
public class ChatServer { /**
* 通道管理器
*/
private Selector selector; private void initServer(int port) throws Exception{ ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel .socket().bind(new InetSocketAddress(port));
// 配置非阻塞
serverChannel .configureBlocking(false); this.selector=Selector.open(); /**
* 将通道管理器和该通道绑定,并为该通道注册selectionKey.OP_ACCEPT事件
* 注册该事件后,当事件到达的时候,selector.select()会返回,
* 如果事件没有到达selector.select()会一直阻塞
* selector.selectNow() 立即返回 无论是否准备好 可能返回0
*/
serverChannel .register(this.selector, SelectionKey.OP_ACCEPT); } /**
* 采用轮训的方式监听selector上是否有需要处理的事件,如果有,进行处理
*/
public void listen() throws Exception {
System.out.println("start------------------->");
while (true){
// 在没有注册事件来到时 将会一直阻塞
selector.select();
Set<SelectionKey> set = selector.selectedKeys();
Iterator<SelectionKey> iterator = set.iterator(); while (iterator.hasNext()){
SelectionKey key = iterator.next();
// 移除当前阻塞队列
iterator.remove();
if(key.isAcceptable()){
ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel channel = server.accept();
channel.configureBlocking(false);
// 服务端发送数据
channel.write(ByteBuffer.wrap(new String("hello client").getBytes()));
// 在客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限
channel.register(this.selector,SelectionKey.OP_READ); }else if(key.isReadable()){
SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(10);
channel.read(buffer); String msg = new String(buffer.array()).trim(); System.out.println("客户端发送过来的讯息:"+msg);
// 在读取后 将柱塞队列数据 改变监听为Accept
ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes());
channel.write(outBuffer);
}
}
} } public static void main(String[] args) throws Exception{
ChatServer server = new ChatServer();
server.initServer(8989);
server.listen();
} }
clien:
package base.nio.chatdemo; import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator; /**
* @program: Lear-Java
* @description: nio 聊天客户端
* @author: Mr.Dai
* @create: 2018-10-05 16:31
**/
public class ChatClient { /**
* 提供柱阻塞队列 管理器
*/
private Selector selector; private void ininCliect(String ip,int port) throws Exception{ SocketChannel channel = SocketChannel.open(); channel .connect(new InetSocketAddress(ip,port)); this.selector=Selector.open(); channel .configureBlocking(false); channel .register(this.selector, SelectionKey.OP_CONNECT); } public void listen() throws Exception { while (true){ selector.select(); Iterator<SelectionKey> ite = selector.selectedKeys().iterator(); while (ite.hasNext()){
SelectionKey key = ite .next();
ite .remove();
if(key.isConnectable()){
SocketChannel channel = (SocketChannel) key.channel();
// 是否准备好连接
if(channel.isConnectionPending()){
channel.finishConnect();
}
channel.configureBlocking(false);
// 向server 发送数据
channel.write(ByteBuffer.wrap("向server 发送数据".getBytes())); channel.register(selector,SelectionKey.OP_READ); }else if(key.isReadable()){
m1(key);
}
}
}
} private void m1(SelectionKey key) throws IOException {
SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(10);
channel.read(buffer);
System.out.println("服务端的消息为:"+new String(buffer.array())); ByteBuffer outBuffer = ByteBuffer.wrap(new String("aaa").getBytes());
channel.write(outBuffer);
} public static void main(String[] args) throws Exception {
ChatClient client = new ChatClient(); client.ininCliect("127.0.0.1",8989);
client.listen();
} }
Java NIO 必知必会(Example)的更多相关文章
- 必知必会之 Java
必知必会之 Java 目录 不定期更新中-- 基础知识 数据计量单位 面向对象三大特性 基础数据类型 注释格式 访问修饰符 运算符 算数运算符 关系运算符 位运算符 逻辑运算符 赋值运算符 三目表达式 ...
- Java面试必知必会:基础
面试考察的知识点多而杂,要完全掌握需要花费大量的时间和精力.但是面试中经常被问到的知识点却没有多少,你完全可以用 20% 的时间去掌握 80% 常问的知识点. 一.基础 包括: 杂七杂八 面向对象 数 ...
- 第5节:Java基础 - 必知必会(下)
第5节:Java基础 - 必知必会(下) 本小节是Java基础篇章的第三小节,主要讲述Java中的Exception与Error,JIT编译器以及值传递与引用传递的知识点. 一.Java中的Excep ...
- 第4节:Java基础 - 必知必会(中)
第4节:Java基础 - 必知必会(中) 本小节是Java基础篇章的第二小节,主要讲述抽象类与接口的区别,注解以及反射等知识点. 一.抽象类和接口有什么区别 抽象类和接口的主要区别可以总结如下: 抽象 ...
- 第3节:Java基础 - 必知必会(上)
第3节:Java基础 - 必知必会(上) 本篇是基础篇的第一小节,我们从最基础的java知识点开始学习.本节涉及的知识点包括面向对象的三大特征:封装,继承和多态,并且对常见且容易混淆的重要概念覆盖和重 ...
- Java并发必知必会第三弹:用积木讲解ABA原理
Java并发必知必会第三弹:用积木讲解ABA原理 可落地的 Spring Cloud项目:PassJava 本篇主要内容如下 一.背景 上一节我们讲了程序员深夜惨遭老婆鄙视,原因竟是CAS原理太简单? ...
- 必知必会之Java注解
必知必会之Java注解 目录 不定期更新中-- 元注解 @Documented @Indexed @Retention @Target 常用注解 @Deprecated @FunctionalInte ...
- Java面试必知必会(扩展)——Java基础
float f=3.4;是否正确? 不正确 3.4是双精度,将双精度赋值给浮点型属于向下转型,会造成精度损失: 因此需要强制类型转换: 方式一:float f=(float)3.4 方式二:float ...
- mysql必知必会系列(一)
mysql必知必会系列是本人在读<mysql必知必会>中的笔记,方便自己以后查看. MySQL. Oracle以及Microsoft SQL Server等数据库是基于客户机-服务器的数据 ...
- 《MySQL必知必会》整理
目录 第1章 了解数据库 1.1 数据库基础 1.1.1 什么是数据库 1.1.2 表 1.1.3 列和数据类型 1.1.4 行 1.1.5 主键 1.2 什么是SQL 第2章 MySQL简介 2.1 ...
随机推荐
- 一.编译nginx
前往nginx.org下载需要的nginx版本,解压之后目录如下: auto : 主要存放辅助configure脚本执行时的文件, 例如判定nginx支持的模块,操作系统可供nginx使用的特性等. ...
- Vagrant + Vbox实战 【转】
原文地址:http://www.cnblogs.com/suihui/p/4362233.html 一.软件下载 1.下载Oracle VM VirtualBox https://www.virtua ...
- 存储过程之rowtype 使用
CREATE OR REPLACE PROCEDURE "DYLYLQX_SC_BA_1" (YWID IN VARCHAR2, FLAG OUT VARCHAR2) IS V_R ...
- rand()与srand()
1.不用srand()的话 两次运行程序产生的随机数序列相同 2.用srand() 两次运行程序产生的随机数则不同 示例程序: #include<iostream> #include< ...
- spring的了解以及简单框架的搭建
了解spring: Spring是一个开源的控制反转(Inversion of Controller)和面向切面(AOP)的框架,目的是为了简化开发. IOC(控制反转): public class ...
- L97
We are young. So let's set the world on fire. We can burn brighter than the sun.我们是青年,让我们点亮世界,释放生命,胜 ...
- zero to one(1)
How to google 这两天把之前的过期的账号重新弄了一下,在vutrl上的账号,普通的话现在2.5$只提供ipv6地址,如果是想google我觉得这个应该没有什么问题,或者可以买***的账号, ...
- BZOJ4836: [Lydsy1704月赛]二元运算
BZOJ4836: [Lydsy1704月赛]二元运算 https://lydsy.com/JudgeOnline/problem.php?id=4836 分析: 分开做,维护两个桶. 分治每次求\( ...
- bzoj 5093 图的价值 —— 第二类斯特林数+NTT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5093 每个点都是等价的,从点的贡献来看,得到式子: \( ans = n * \sum\li ...
- shell ss命令
ss命令用来显示处于活动状态的套接字信息.ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容.但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比net ...