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框架的核心配置文 ...
随机推荐
- AVR汇编(四):数据传送指令
AVR汇编(四):数据传送指令 AVR指令主要分为五类:算术和逻辑指令.分支指令.位操作指令.数据传送指令.MCU控制指令,今天我们先来认识其中最常用的数据传送指令. 汇编程序的编写.编译和调试 学习 ...
- 优化 Redis 集群缓存分配:解决节点间分配不均导致内存溢出问题
一.Redis 集群部署简介 在现代应用程序中,缓存被广泛应用以提高性能和减轻后端数据库的压力.本文将探讨面对 Redis 集群缓存分配不均问题时的解决方法. 我们的 Redis 集群部署包括 3 主 ...
- GaoNeng:我是如何为OpenTiny贡献新组件的?
本文共10076字,预计阅读20分钟 大家好啊,又是我GaoNeng.最近在给OpenTiny做贡献,感觉renderless这个架构还是挺有意思的,就贡献了一个color-picker组件,简单写篇 ...
- VulnStack - ATT&CK红队评估实战(一) Writeup
VulnStack - ATT&CK红队评估实战(一) Writeup VulnStack(一)环境搭建 项目地址 http://vulnstack.qiyuanxuetang.net/vul ...
- 银河麒麟使用kickstart二次打包制作安装镜像ISO
系统:银河麒麟 V10 SP2 服务器:百信恒山 TS02F-F30 安装方式:服务器挂载ISO镜像进行安装 1.安装 mkisofs 软件包: #yum install genisoimage 2. ...
- 文心一言 VS 讯飞星火 VS chatgpt (88)-- 算法导论8.3 1题
一.用go语言,参照图 8-3 的方法,说明 RADIX-SORT在下列英文单词上的操作过程:COW,DOG,SEA,RUG,ROW,MOB, BOX, TAB, BAR, EAR,TAR, DIG, ...
- 线段树hdu-4027
Smiling & Weeping ---- 姑娘,倘若,我双手合十的愿望里有你呢 Problem Description A lot of battleships of evil are ...
- Spring Boot中自动装配机制的原理
SpringBoot中自动装配机制的原理 1.自动装配,简单来说就是自动把第三方组件的Bean装载到Spring IOC容器里面,不需要开发人员再去写Bean的装配配置, 2.在Spring Boot ...
- Spring Event 观察者模式, 业务解耦神器
观察者模式在实际开发过程中是非常常见的一种设计模式. Spring Event的原理就是观察者模式,只不过有Spring的加持,让我们更加方便的使用这一设计模式. 一.什么是观察者模式 概念: 观察者 ...
- jdk8环境变量
JAVA_HOME C:\Program Files\Java\jdk1.8.0_333 Path%JAVA_HOME%\bin%JAVA_HOME%\jre\bin CLASSPATH.%JAVA_ ...