单线程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)的更多相关文章

  1. 如何创建一个简单的C++同步锁框架(译)

    翻译自codeproject上面的一篇文章,题目是:如何创建一个简单的c++同步锁框架 目录 介绍 背景 临界区 & 互斥 & 信号 临界区 互斥 信号 更多信息 建立锁框架的目的 B ...

  2. WInform 创建一个简单的WPF应用

    (一)创建一个简单的WPF应用 首先,在这里我要说明的是:这里的例子,都是通过控制台程序来创建WPF应用,而非使用现成的WPF模版.因为WPF模版封装了创建WPF应用所需要的各种基本元素,并不利于我们 ...

  3. 3.2 Lucene实战:一个简单的小程序

    在讲解Lucene索引和检索的原理之前,我们先来实战Lucene:一个简单的小程序! 一.索引小程序 首先,new一个java project,名字叫做LuceneIndex. 然后,在project ...

  4. 如何创建一个简单的Visual Studio Code扩展

    注:本文提到的代码示例下载地址>How to create a simple extension for VS Code VS Code 是微软推出的一款轻量级的代码编辑器,免费,开源,支持多种 ...

  5. 《Entity Framework 6 Recipes》翻译系列 (3) -----第二章 实体数据建模基础之创建一个简单的模型

    第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以 ...

  6. Windows 8.1 应用再出发 (WinJS) - 创建一个简单项目

    前面几篇我们介绍了如何利用 C# + XAML 完成Windows Store App 功能的实现,接下来的几篇我们来看看如何利用 Html + WinJS 来完成这些功能. 本篇我们使用WinJS ...

  7. ADF_General JSF系列1_创建一个简单的JSF Application

    2015-02-17 Creatd By BaoXinjian

  8. IntelliJ IDEA 15 部署Tomcat及创建一个简单的Web工程

    一.部署Tomcat 二.创建一个简单的Web工程 2.1创建一个新工程 创建一个新工程 设置JDK及选择Web Application (创建的是Web工程) 点击Next,选择工作空间,起个工程名 ...

  9. Symfony2之创建一个简单的web应用

    Symfony2——创建bundle       bundle就像插件或者一个功能齐全的应用,我们在应用层上开发的应用的所有代码,包括:PHP文件.配置文件.图片.css文件.js文件等都会包含在bu ...

  10. 如何创建一个简单的struts2程序

    如何创建一个简单的Struts2程序 “计应134(实验班) 凌豪” 1.创建一个新的Web项目test(File->new->Web Project) 2.Struts2框架的核心配置文 ...

随机推荐

  1. Feign的超时时间如何设置,我研究了4种情况

    大家好,我是三友~~ 今天来聊一聊前段时间看到的一个面试题,也是在实际项目中需要考虑的一个问题,Feign的超时时间如何设置? Feign的超时时间设置方式并不固定,它取决于Feign在项目中是如何使 ...

  2. 头疼!卷积神经网络是什么?CNN结构、训练与优化一文全解

    本文全面探讨了卷积神经网络CNN,深入分析了背景和重要性.定义与层次介绍.训练与优化,详细分析了其卷积层.激活函数.池化层.归一化层,最后列出其训练与优化的多项关键技术:训练集准备与增强.损失函数.优 ...

  3. 【Bash】rm -r 与 rmdir 区别

    目录 背景 二者区别 rmdir rm -r rm -rf 测试过程 配置环境 rmdir rm -r rm -rf 参考资料 背景 今天学弟在使用 NVMe-over-TCP 时发现无法卸载 nvm ...

  4. 通过AOP拦截Spring Boot日志并将其存入数据库

    本文分享自华为云社区<Spring Boot入门(23):[实战]通过AOP拦截Spring Boot日志并将其存入数据库>,作者:bug菌. 前言 在软件开发中,常常需要记录系统运行时的 ...

  5. 解密Prompt系列14. LLM Agent之搜索应用设计:WebGPT & WebGLM & WebCPM

    前两章,我们分别介绍了基于微调和prompt的工具调用方案,核心都是如何让大模型和工具进行交互,包括生成工具调用语句和处理工具调用请求.不过在实际应用中,想要设计一个可以落地的LLM Agent,需要 ...

  6. VR国标

    <软件基本要求与测试方法>

  7. MySQL面试题——隔离级别相关面试题

    隔离级别相关面试题 MySQL事务隔离级别 未提交读--可以读到其他事务未提交的数据(最新的版本) 错误现象:脏读.不可重复读.幻读的现象 提交读(RC)--可以读到其他事务已提交的数据(最新已提交的 ...

  8. Solution -「洛谷 P1852」跳跳棋

    Description Link. 在一个数轴上给你三个点,移动方法是彼此为中点进行跳跃,不能同时越过两颗棋子. 给出初始状态和目标状态,问能否从初始状态跳到目标状态.若能,输出最少步数. 棋子之间互 ...

  9. oracle数据库性能监控常用sql

    因执行时间较长建议使用plsql等第三方工具执行 --1.监控sga内存分配信息select * from v$sgainfo;--2.监控每个用户的磁盘io及io命中率select v$sess_i ...

  10. 小白CNN入门指导

    小白CNN入门指导 这几天一直在小白入门学习卷积层以准备组会,以下是我自学理解内容,若有错误的地方请各位评论指出 数学部分 一 卷积层 \[输入 32*32*3 (input neurons) \] ...