Reactor实战,创建一个简单的单线程Reactor(理解了就相当于理解了多线程的Reactor)
单线程Reactor
package org.example.utils.echo.single;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class EchoServerReactor implements Runnable{
Selector selector;
ServerSocketChannel serverSocketChannel;
EchoServerReactor() throws IOException {
//Reactor初始化
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
InetSocketAddress address =
new InetSocketAddress("localhost",
8848);
//非阻塞
serverSocketChannel.configureBlocking(false);
//分步处理,第一步,接收accept事件
SelectionKey sk =
serverSocketChannel.register(selector,0,new AcceptorHandler());
// SelectionKey.OP_ACCEPT
serverSocketChannel.socket().bind(address);
System.out.println("服务端已经开始监听:"+address);
sk.interestOps(SelectionKey.OP_ACCEPT);
}
@Override
public void run() {
try {
while (!Thread.interrupted()){
selector.select();
Set<SelectionKey> selected=selector.selectedKeys();
Iterator<SelectionKey> it=selected.iterator();
while (it.hasNext()){
SelectionKey sk=it.next();
dispatch(sk);
}
selected.clear();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void dispatch(SelectionKey sk) {
Runnable handler=(Runnable) sk.attachment();
if (handler!=null){
handler.run();
}
}
class AcceptorHandler implements Runnable{
@Override
public void run() {
try {
SocketChannel channel=serverSocketChannel.accept();
if (channel!=null)
new EchoHandler(selector,channel);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) throws IOException {
new Thread(new EchoServerReactor()).start();
}
}
package org.example.utils.echo.single;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
public class EchoHandler implements Runnable{
final SocketChannel channel;
final SelectionKey sk;
final ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
static final int RECIEVING=0,SENDING=1;
int state=RECIEVING;
EchoHandler(Selector selector,SocketChannel c) throws IOException {
channel=c;
c.configureBlocking(false);
sk=channel.register(selector,0);
sk.attach(this);
sk.interestOps(SelectionKey.OP_READ);
selector.wakeup();
}
@Override
public void run() {
try {
if (state==SENDING){
channel.write(byteBuffer);
byteBuffer.clear();
sk.interestOps(SelectionKey.OP_READ);
state=RECIEVING;
}else if (state==RECIEVING){
int length=0;
while ((length=channel.read(byteBuffer))>0)
{
System.out.println(new String(byteBuffer.array(),0,length));
}
byteBuffer.flip();
sk.interestOps(SelectionKey.OP_WRITE);
state=SENDING;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
结果:

原理无非就是:

多线程,无非就是搞多个Reactor , 一个专门接受accept , 一个专门dispatch , 再搞一个多线程池处理handle
这里面最主要的就是
handle类,sk.attach(this);把对象传回reactor
参考文献:
java高并发核心编程. 卷1,NIO、Netty、Redis、ZooKeeper (尼恩)
Reactor实战,创建一个简单的单线程Reactor(理解了就相当于理解了多线程的Reactor)的更多相关文章
- 如何创建一个简单的C++同步锁框架(译)
翻译自codeproject上面的一篇文章,题目是:如何创建一个简单的c++同步锁框架 目录 介绍 背景 临界区 & 互斥 & 信号 临界区 互斥 信号 更多信息 建立锁框架的目的 B ...
- WInform 创建一个简单的WPF应用
(一)创建一个简单的WPF应用 首先,在这里我要说明的是:这里的例子,都是通过控制台程序来创建WPF应用,而非使用现成的WPF模版.因为WPF模版封装了创建WPF应用所需要的各种基本元素,并不利于我们 ...
- 3.2 Lucene实战:一个简单的小程序
在讲解Lucene索引和检索的原理之前,我们先来实战Lucene:一个简单的小程序! 一.索引小程序 首先,new一个java project,名字叫做LuceneIndex. 然后,在project ...
- 如何创建一个简单的Visual Studio Code扩展
注:本文提到的代码示例下载地址>How to create a simple extension for VS Code VS Code 是微软推出的一款轻量级的代码编辑器,免费,开源,支持多种 ...
- 《Entity Framework 6 Recipes》翻译系列 (3) -----第二章 实体数据建模基础之创建一个简单的模型
第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以 ...
- Windows 8.1 应用再出发 (WinJS) - 创建一个简单项目
前面几篇我们介绍了如何利用 C# + XAML 完成Windows Store App 功能的实现,接下来的几篇我们来看看如何利用 Html + WinJS 来完成这些功能. 本篇我们使用WinJS ...
- ADF_General JSF系列1_创建一个简单的JSF Application
2015-02-17 Creatd By BaoXinjian
- IntelliJ IDEA 15 部署Tomcat及创建一个简单的Web工程
一.部署Tomcat 二.创建一个简单的Web工程 2.1创建一个新工程 创建一个新工程 设置JDK及选择Web Application (创建的是Web工程) 点击Next,选择工作空间,起个工程名 ...
- Symfony2之创建一个简单的web应用
Symfony2——创建bundle bundle就像插件或者一个功能齐全的应用,我们在应用层上开发的应用的所有代码,包括:PHP文件.配置文件.图片.css文件.js文件等都会包含在bu ...
- 如何创建一个简单的struts2程序
如何创建一个简单的Struts2程序 “计应134(实验班) 凌豪” 1.创建一个新的Web项目test(File->new->Web Project) 2.Struts2框架的核心配置文 ...
随机推荐
- 带你快速上手HetuEngine
本文分享自华为云社区<[手把手带你玩转HetuEngine](一)HetuEngine快速上手>,作者:HetuEngine九级代言. HetuEngine是什么 HetuEngine是华 ...
- 手把手教你使用人工智能生成游戏 3D 素材
引言 生成式 AI 已成为游戏开发中艺术工作流的重要组成部分.然而,正如我在 之前的文章 中描述的,从文本到 3D 的实用性仍落后于 2D.不过,这种情况正在改变.本文我们将重新审视 3D 素材生成的 ...
- BUGKU逆向reverse 1-8题
练习IDA两年半 打开尘封已久的bugku,从题目中练习使用,现在都已经是新版本了 orz 入门逆向 运行baby.exe将解压后的baby.exe拖到IDA里面主函数中找到mov指令 可以看到这里就 ...
- 【升职加薪秘籍】我在服务监控方面的实践(7)-业务维度的redis监控
大家好,我是蓝胖子,关于性能分析的视频和文章我也大大小小出了有一二十篇了,算是已经有了一个系列,之前的代码已经上传到github.com/HobbyBear/performance-analyze,接 ...
- ShardingSphere实战
前言 本文主要从sharding最新版本5.1.2版本入手搭建,按主键ID和时间进行分表. 本文主要介绍搭建过程,有兴趣了解shardingsphere的同学可以先自行查阅相关资料. shardsph ...
- numpy中的nan (无穷小)注意点
- oracle数据库性能监控常用sql
因执行时间较长建议使用plsql等第三方工具执行 --1.监控sga内存分配信息select * from v$sgainfo;--2.监控每个用户的磁盘io及io命中率select v$sess_i ...
- vcpkg manifest 的使用
最近项目上要使用 CMakeLists 管理,由于 Windows 版本有依赖到 vcpkg 提供的库,所以需要使用 vcpkg manifest 来统一设置库的版本,方便后续维护 推荐一个文章,介绍 ...
- 【matplotlib 实战】--饼图
饼图,或称饼状图,是一个划分为几个扇形的圆形统计图表.在饼图中,每个扇形的弧长(以及圆心角和面积)大小,表示该种类占总体的比例,且这些扇形合在一起刚好是一个完全的圆形. 饼图最显著的功能在于表现&qu ...
- 《流畅的Python》 读书笔记 第三章字典和集合 20231017
第3章 字典和集合 dict 类型是 Python 语言的基石 模块的命名空间.实例的属性和函数的关键字参数中都可以看到字典的身影 跟它有关的内置函数都在__builtins__.__dict__ 模 ...