单线程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. shiro框架基本概念介绍

    什么是Shiro: Shiro 是一个强大灵活的开源安全框架,可以完全处理身份验证.授权.加密和会话管理 Shiro的核心功能包括: 身份验证(Authentication):验证用户的身份,确保用户 ...

  2. 入门篇-其之二-Java基础知识

    目录 对第一个Java程序的思考 外层结构--类 内层结构--main方法 输出语句 注释 单行注释 多行注释 文档注释 文档注释常用标签 使用javadoc命令生成网页风格的文档 阿里巴巴Java开 ...

  3. ipa客户端安装

    ipa客户端安装 安装操作官网 非交互式安装IPa客户端 kinit admin ipa host-find ipa host-add ipa host-add --help ipa host-add ...

  4. [Python] 今天开始学习Python3了, 纪念一下

    #! /usr/bin/env python3 import time print("你好, 请告诉我你的名字.") name = input("名前: ") ...

  5. 【krpano】 ASP浏览量插件

    简述 这是一个Asp版krpano统计访问量案例,运用asp代码控制增值来实现的功能:现将案例上传网站供大家学习研究,希望对大家有所帮助. 功能 用户进入网页增值或刷新增值. 案例展示 所有文件如下图 ...

  6. 两个例子带你入门 Disruptor

    Disruptor 是英国外汇交易公司 LMAX 开发的一个高性能队列.很多知名开源项目里,比如 canal .log4j2. storm 都是用了 Disruptor 以提升系统性能 . 这篇文章, ...

  7. TCP vs UDP:揭秘可靠性与效率之争

    概述 今天我们开始主要讲解TCP的相关知识点.在之前讲解分层章节的时候,我们提到过一个重要观点.在网络层及以下几层,更多的是让主机与主机建立连接,也就是说你的电脑需要知道另一台电脑在哪里才能连接上它. ...

  8. 文心一言 VS 讯飞星火 VS chatgpt (106)-- 算法导论10.1 4题

    四.用go语言,重写 ENQUEUE 和 DEQUEUE 的代码,使之能处理队列的下溢和上溢. 文心一言: 在 Go 语言中,我们可以使用切片来实现队列.下面是如何实现 ENQUEUE 和 DEQUE ...

  9. Redis系列之——API的使用

    文章目录 一 通用命令 1.1 通用命令 1.2 数据结构和内部编码 1.3 单线程架构 1.3.1 单线程架构, 1.3.2 单线程为什么这么快 1.3.3 注意 二 字符串类型 2.1 字符串键值 ...

  10. ChatGPT 是如何产生心智的?

    一.前言 - ChatGPT真的产生心智了吗? 来自斯坦福大学的最新研究结论,一经发出就造成了学术圈的轰动,"原本认为是人类独有的心智理论(Theory of Mind,ToM),已经出现在 ...