热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JAVA自定义EVENTBUS简单实现

packagecom.wosai.constant;importcom.wosai.data.util.CollectionUtil;importcom.wosai.eventbu

package com.wosai.constant;
import com.wosai.data.util.CollectionUtil;
import com.wosai.eventbus.Event;
import com.wosai.eventbus.EventListener;
import com.wosai.eventbus.SimpleEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Description:自定义eventBus实现
* @Author jerry
* Date 2020/1/2 5:43 下午
**/
public class EventBus {
private static final Logger logger = LoggerFactory.getLogger(com.wosai.eventbus.EventBus.class);
private Map> listeners;
private com.wosai.eventbus.EventBus.EventLoop[] eventLoops;
private int maxQueueSizeForWarning = 5;
private int maxWarningCount = 10 ;
private AtomicInteger remainingWarningCount = new AtomicInteger(maxWarningCount) ;
private int cOncurrency= 0;
public EventBus(int concurrency) {
this.listeners = new HashMap>();
this.eventLoops = new com.wosai.eventbus.EventBus.EventLoop[concurrency];
for(int i=0; i this.eventLoops[i] = new com.wosai.eventbus.EventBus.EventLoop();
}
this.cOncurrency= concurrency;
}
public EventBus(int concurrency, int maxQueueSizeForWarning) {
this(concurrency);
this.maxQueueSizeForWarning = maxQueueSizeForWarning;
}
public EventBus() {
this(2);
}
public void start() {
for(com.wosai.eventbus.EventBus.EventLoop loop: eventLoops) {
loop.start();
}
}
public void subscribe(String event, EventListener listener) {
Set listenerSet = listeners.get(event);
if (listenerSet == null) {
listenerSet = new LinkedHashSet();
listeners.put(event, listenerSet);
}
listenerSet.add(listener);
}
public void post(Event event) {
eventLoops[event.getKey()].postEvent(event);
}
private void dispatchEvent(final Event event) {
Set listenerSet = listeners.get(event.getName());
if (listenerSet != null) {
for(final EventListener listener: listenerSet) {
try {
listener.handle(event);
}catch(Throwable e){
// WARN: exception in event handler
logger.warn("Unexpected exception in event handler.", e);
}
}
}else{
// WARN: no event listener
logger.warn("Received event {} w/o listeners.", event.getName());
}
}
public void shutdown() {
for(com.wosai.eventbus.EventBus.EventLoop loop: eventLoops) {
loop.stop();
}
}
public Map getInfo(){
List list = new ArrayList();
if(eventLoops != null){
for (int i = 0; i com.wosai.eventbus.EventBus.EventLoop eventLoop = eventLoops[i];
int queueSize = eventLoop.eventQueue.size();
list.add(CollectionUtil.hashMap(
"index", i,
"queueSize", queueSize
));
}
}
return CollectionUtil.hashMap(
"eventLoops", list
);
}
class EventLoop {
private LinkedBlockingQueue eventQueue = new LinkedBlockingQueue();
private volatile boolean stopped = true;
private Thread _t;
public void start() {
if (!stopped) {
return;
}
stopped = false;
_t = new Thread(new Runnable() {
@Override
public void run() {
while(!stopped) {
try {
Event event = eventQueue.take();
dispatchEvent(event);
}
catch (InterruptedException e) {
// Continue next iteration.
}
}
logger.info("event loop stopped");
}
});
_t.setDaemon(true);
_t.setName("eventloop " + _t.getName());
_t.start();
}
public void stop() {
if (stopped)
return;
stopped = true;
_t.interrupt();
}
public void postEvent(Event e) {
int queueSize = eventQueue.size();
if(queueSize <= maxQueueSizeForWarning){
remainingWarningCount.set(maxWarningCount);
}else{
if(remainingWarningCount.getAndDecrement() > 0){
logger.warn("too many events in queue! current size: {} warning max: {}", queueSize, maxQueueSizeForWarning);
}
}
for (int i = 0; i<3; ++i) {
try {
eventQueue.put(e);
return;
} catch (InterruptedException ex) {
}
}
logger.error("lost event {}", e.getName());
}
}
//eventloop分区
public static class EventLoopMultiple{
private int start; // eventloop 起始位置,从0开始
private int count; // eventloop 数量
private int end; // eventloop 结束位置
public EventLoopMultiple(int start, int count, int end) {
this.start = start;
this.count = count;
this.end = end;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public int getCount() {
return count;
}
@Override
public String toString() {
return "EventLoopMultiple [start=" + start + ", end=" + end + ", count=" + count + "]";
}
}
public int getConcurrency() {
return concurrency;
}
public static void main(String[] args) throws Exception {
final com.wosai.eventbus.EventBus bus = new com.wosai.eventbus.EventBus();
bus.subscribe("success", new EventListener() {
@Override
public void handle(Event event) {
System.out.println("on event " + event + " " + Thread.currentThread().getId());
bus.post(new SimpleEvent("postSuccess", null));
bus.post(new SimpleEvent("final", 1, "first final"));
}
});
bus.subscribe("postSuccess", new EventListener() {
@Override
public void handle(Event event) {
System.out.println("on event " + event + " " + Thread.currentThread().getId());
bus.post(new SimpleEvent("final", "second final"));
}
});
bus.subscribe("final", new EventListener() {
@Override
public void handle(Event event) {
System.out.println("handler 1 on event " + event + " " + Thread.currentThread().getId());
}
});
bus.subscribe("final", new EventListener() {
@Override
public void handle(Event event) {
System.out.println("handler 2 on event " + event + " " + Thread.currentThread().getId());
}
});
bus.start();
bus.post(new SimpleEvent("success"));
Thread.sleep(2000);
bus.shutdown();
}
}

推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • importjava.util.ArrayList;publicclassPageIndex{privateintpageSize;每页要显示的行privateintpageNum ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
author-avatar
寡凫lo单鹄官方
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有