最近正在学习EventBus源码,正好总结记录一下~ EventBus是一个针对Android优化的发布-订阅事件总线,它简化了应用程序内各个组件之间的通信,尤其是fragment和fragment之间的通信。优点是将发送者和接收者解耦,并且开销小,代码优雅。 一、EventBus的三要素 Event:事件,可以是任意类型的对象; Subscriber:事件订阅者,事件处理方法可以随意取,但需要添加注解@Subscribe,并且要指定线程模型(默认POSTING); Publisher:事件发布者,可以在任意线程任意位置发送事件,直接调用post()即可; EventBus的4种线程模型: POSTING(默认):发布事件和接收事件在同一个线程中,即事件在哪个线程中发布,事件处理就在哪个线程中执行; MAIN:事件处理会在UI线程中执行; ASYNC:事件不论在哪个线程中发布,事件处理都会在新建的子线程中执行; BACKGROUND:事件在UI线程中发布,事件处理会在新建的线程中执行,事件在子线程中发布,事件处理就会在发布事件的线程中执行; 二、源码解析 构造方法 一般我们会调用EventBus.getDefault()来获取EventBus实例,先来看下getDefault()代码: public static EventBus getDefault() { if (defaultInstance == null) { synchronized (EventBus.class) { if (defaultInstance == null) { defaultInstance = new EventBus(); } } } return defaultInstance; } 上面代码是一个单例模式,采用了双重检查模式,如果defaultInstance为空,就new一个EventBus对象,来看下EventBus()里的代码: private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder(); public EventBus() { this(DEFAULT_BUILDER); } this调用的是另一个构造方法: EventBus(EventBusBuilder builder) { logger = builder.getLogger(); subscriptionsByEventType = new HashMap<>(); typesBySubscriber = new HashMap<>(); stickyEvents = new ConcurrentHashMap<>(); mainThreadSupport = builder.getMainThreadSupport(); mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null; backgroundPoster = new BackgroundPoster(this); asyncPoster = new AsyncPoster(this); indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0; // builder.ignoreGeneratedIndex 是否忽略注解器生成的MyEventBusIndex subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes, builder.strictMethodVerification, builder.ignoreGeneratedIndex); logSubscriberExceptions = builder.logSubscriberExceptions; logNoSubscriberMessages = builder.logNoSubscriberMessages; sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent; sendNoSubscriberEvent = builder.sendNoSubscriberEvent; throwSubscriberException = builder.throwSubscriberException; // eventInheritance 是否向上查找事件的父类 eventInheritance = builder.eventInheritance; executorService = builder.executorService; } 这个方法里初始化了一些属性,构造方法里传入了一个EventBusBuilder,而上面的DEFAULT_BUILDER就是一个默认的EventBusBuilder,使用这个方法可以对EventBus进行配置,使用自定义参数创建EventBus实例,也可以创建默认EventBus实例。 事件发送 获取到EventBus实例,我们调用post()方法来发送事件,来看post方法代码: public void post(Object event) { // PostingThreadState保存着事件队列和线程状态信息 PostingThreadState postingState = currentPostingThreadState.get(); // 获取事件队列,并将当前事件插入事件队列 List eventQueue = postingState.eventQueue; eventQueue.add(event); if (!postingState.isPosting) { postingState.isMainThread = isMainThread(); postingState.isPosting = true; if (postingState.canceled) { throw new EventBusException("Internal error. Abort state was not reset"); } try { // 处理队列中的所有事件 while (!eventQueue.isEmpty()) { postSingleEvent(eventQueue.remove(0), postingState); } } finally { postingState.isPosting = false; postingState.isMainThread = false; } } } 首先从PostingThreadState取出事件队列,然后将当前事件插入队列,最后依次调用postSingleEvent()方法处理队列中事件,并移除该事件。进入postSingleEvent()代码: private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { Class eventClass = event.getClass(); boolean subscriptionFound = false; // eventInheritance表示是否向上查找事件的父类,在EventBusBuilder中声明,默认为true if (eventInheritance) { List> eventTypes = lookupAllEventTypes(eventClass); int countTypes = eventTypes.size(); for (int h = 0; h < countTypes; h++) { Class clazz = eventTypes.get(h); subscriptionFound |= postSingleEventForEventType(event, postingState, clazz); } } else { subscriptionFound = postSingleEventForEventType(event, postingState, eventClass); } // 找不到事件 if (!subscriptionFound) { if (logNoSubscriberMessages) { logger.log(Level.FINE, "No subscribers registered for event " + eventClass); } if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) { post(new NoSubscriberEvent(this, event)); } } } 当eventInheritance为true时,通过lookupAllEventTypes()找到所有的父类事件并存到List中,遍历该List,调用postSingleEventForEventType()对事件进行处理。当eventInheritance为false时,直接调用postSingleEventForEventType()方法,显而易见,最后都走到这个postSingleEventForEventType()方法,我们来看源码: private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class eventClass) { CopyOnWriteArrayList subscriptions; // 同步取出订阅对象集合 synchronized (this) { subscriptions = subscriptionsByEventType.get(eventClass); } if (subscriptions != null && !subscriptions.isEmpty()) { // 遍历集合,将事件event和订阅对象subscription赋值给postingState for (Subscription subscription : subscriptions) { postingState.event = event; postingState.subscription = subscription; boolean aborted = false; try { postToSubscription(subscription, event, postingState.isMainThread); aborted = postingState.canceled; } finally { postingState.event = null; postingState.subscription = null; postingState.canceled = false; } if (aborted) { break; } } return true; } return false; } 同步取出订阅对象集合subscriptions,遍历subscriptions,将事件event和订阅对象subscription赋值给postingState,然后调用postToSubscription(),我们再看postToSubscription()源码: private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) { switch (subscription.subscriberMethod.threadMode) { case POSTING: invokeSubscriber(subscription, event); break; case MAIN: if (isMainThread) { invokeSubscriber(subscription, event); } else { mainThreadPoster.enqueue(subscription, event); } break; case MAIN_ORDERED: if (mainThreadPoster != null) { mainThreadPoster.enqueue(subscription, event); } else { // temporary: technically not correct as poster not decoupled from subscriber invokeSubscriber(subscription, event); } break; case BACKGROUND: if (isMainThread) { backgroundPoster.enqueue(subscription, event); } else { invokeSubscriber(subscription, event); } break; case ASYNC: asyncPoster.enqueue(subscription, event); break; default: throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode); } } 这个方法里取出了订阅方法的线程模型,根据线程模型来分别处理: 如果线程模型是POSTING,就通过反射直接运行订阅的方法; 如果线程模型是MAIN,提交事件的是主线程,就通过反射直接运行订阅的方法,如果不是主线程,则通过mainThreadPoster将订阅事件添加到主线程队列里面; 如果线程模型是BACKGROUND,提交事件的是主线程,则通过backgroundPoster将订阅事件添加到子线程队列里面,如果不是主线程,就通过反射直接运行订阅的方法; 如果线程模型是ASYNC,就通过asyncPoster将订阅事件添加到子线程队列里面; 这就和我们上面提到的4种线程模型对上了~ 事件注册 我们发送了事件,想要接收事件的话,需要先调用register()注册,源码如下: public void register(Object subscriber) { Class subscriberClass = subscriber.getClass(); // 获取订阅者订阅方法集合 List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass); synchronized (this) { // 遍历订阅者方法集合,注册订阅者 for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod); } } } register一共做了两件事:通过findSubscriberMethods()查找订阅者订阅方法集合subscriberMethods,以及遍历subscriberMethods集合,调用subscribe()进行订阅者的注册。 findSubscriberMethods() 我们先来看findSubscriberMethods()方法,源码如下: List findSubscriberMethods(Class subscriberClass) { // 从缓存中获取订阅者方法集合 List subscriberMethods = METHOD_CACHE.get(subscriberClass); if (subscriberMethods != null) { return subscriberMethods; } // ignoreGeneratedIndex默认false,在EventBusBuilder中声明,表示是否忽略注解器生成的MyEventBusIndex if (ignoreGeneratedIndex) { subscriberMethods = findUsingReflection(subscriberClass); } else { // 获取订阅者方法集合 subscriberMethods = findUsingInfo(subscriberClass); } if (subscriberMethods.isEmpty()) { throw new EventBusException("Subscriber " + subscriberClass + " and its super classes have no public methods with the @Subscribe annotation"); } else { // 将订阅方法集合放入缓存 METHOD_CACHE.put(subscriberClass, subscriberMethods); return subscriberMethods; } } 这个方法先从缓存中获取订阅者方法集合subscriberMethods,如果不为空,直接返回,如果为空就通过ignoreGeneratedIndex这个变量判断调用哪个方法,ignoreGeneratedIndex默认false,所以会调用findUsingInfo()方法获取订阅者方法集合subscriberMethods,拿到集合后将其放入缓存中。我们再看findUsingInfo()方法: private List findUsingInfo(Class subscriberClass) { FindState findState = prepareFindState(); findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { // 获取订阅者信息 findState.subscriberInfo = getSubscriberInfo(findState); if (findState.subscriberInfo != null) { // 获取订阅方法相关信息 SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods(); for (SubscriberMethod subscriberMethod : array) { if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) { // 向订阅方法集合中添加订阅方法对象 findState.subscriberMethods.add(subscriberMethod); } } } else { findUsingReflectionInSingleClass(findState); } findState.moveToSuperclass(); } // 回收findState并返回订阅方法集合 return getMethodsAndRelease(findState); } 首先调用prepareFindState()初始化findState,通过getSubscriberInfo()方法获取订阅者信息subscriberInfo,获取到信息后调用getSubscriberMethods()获取订阅方法相关信息,遍历相关信息,向订阅方法集合subscriberMethods中添加订阅方法对象subscriberMethod,最后调用getMethodsAndRelease()回收findState并返回订阅方法集合;如果没有获取到订阅者信息subscriberInfo,调用 findUsingReflectionInSingleClass()。 private void findUsingReflectionInSingleClass(FindState findState) { Method[] methods; try { // This is faster than getMethods, especially when subscribers are fat classes like Activities // 通过反射获取订阅者中所有方法 methods = findState.clazz.getDeclaredMethods(); } catch (Throwable th) { // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149 methods = findState.clazz.getMethods(); findState.skipSuperClasses = true; } for (Method method : methods) { int modifiers = method.getModifiers(); if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { Class[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1) { Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class); if (subscribeAnnotation != null) { Class eventType = parameterTypes[0]; if (findState.checkAdd(method, eventType)) { ThreadMode threadMode = subscribeAnnotation.threadMode(); // 将订阅方法保存到findState中 findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, subscribeAnnotation.priority(), subscribeAnnotation.sticky())); } } } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) { String methodName = method.getDeclaringClass().getName() + "." + method.getName(); throw new EventBusException("@Subscribe method " + methodName + "must have exactly 1 parameter but has " + parameterTypes.length); } } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) { String methodName = method.getDeclaringClass().getName() + "." + method.getName(); throw new EventBusException(methodName + " is a illegal @Subscribe method: must be public, non-static, and non-abstract"); } } } 调用getDeclaredMethods()通过反射获取订阅者中所有方法,遍历所有方法,根据方法类型、参数、注解找到订阅方法,将订阅方法保存到findState中。 subscribe() // Must be called in synchronized block private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { Class eventType = subscriberMethod.eventType; // 创建订阅对象newSubscription Subscription newSubscription = new Subscription(subscriber, subscriberMethod); // 根据事件类型eventType获取订阅对象集合subscriptions CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType); if (subscriptions == null) { subscriptions = new CopyOnWriteArrayList<>(); // 将订阅对象集合subscriptions保存到Map集合subscriptionsByEventType中 subscriptionsByEventType.put(eventType, subscriptions); } else { // 判断订阅者是否已经被注册 if (subscriptions.contains(newSubscription)) { throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType); } } int size = subscriptions.size(); for (int i = 0; i <= size; i++) { if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) { // 按照优先级将newSubscription插入订阅对象集合subscriptions中 subscriptions.add(i, newSubscription); break; } } // 通过订阅者subscriber获取事件类型集合subscribedEvents List> subscribedEvents = typesBySubscriber.get(subscriber); if (subscribedEvents == null) { subscribedEvents = new ArrayList<>(); // 将subscribedEvents存到Map集合typesBySubscriber中 typesBySubscriber.put(subscriber, subscribedEvents); } // 将事件类型eventType放入subscribedEvents中 subscribedEvents.add(eventType); if (subscriberMethod.sticky) { if (eventInheritance) { // 黏性事件处理 // Existing sticky events of all subclasses of eventType have to be considered. // Note: Iterating over all events may be inefficient with lots of sticky events, // thus data structure should be changed to allow a more efficient lookup // (e.g. an additional map storing sub classes of super classes: Class -> List). Set, Object>> entries = stickyEvents.entrySet(); for (Map.Entry, Object> entry : entries) { Class candidateEventType = entry.getKey(); if (eventType.isAssignableFrom(candidateEventType)) { Object stickyEvent = entry.getValue(); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } } else { Object stickyEvent = stickyEvents.get(eventType); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } } subscribe()主要做了两件事:一件是将订阅对象集合subscriptions保存到Map集合subscriptionsByEventType中,将事件类型集合subscribedEvents保存到Map集合typesBySubscriber中;一件是对黏性事件的处理。 事件取消注册 取消注册调用unregister()方法,代码如下: /** Unregisters the given subscriber from all event classes. */ public synchronized void unregister(Object subscriber) { // 通过订阅者subscriber找到事件类型集合subscribedTypes List> subscribedTypes = typesBySubscriber.get(subscriber); if (subscribedTypes != null) { for (Class eventType : subscribedTypes) { unsubscribeByEventType(subscriber, eventType); } // 将订阅者subscriber对应的事件类型从集合中移除 typesBySubscriber.remove(subscriber); } else { logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass()); } } 先获取事件类型集合subscribedTypes,遍历该集合,调用unsubscribeByEventType()方法,并将订阅者subscriber对应的事件类型从集合subscribedTypes中移除。unsubscribeByEventType()代码: /** Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber. */ private void unsubscribeByEventType(Object subscriber, Class eventType) { // 获取对应的订阅对象集合subscriptions List subscriptions = subscriptionsByEventType.get(eventType); if (subscriptions != null) { int size = subscriptions.size(); for (int i = 0; i < size; i++) { Subscription subscription = subscriptions.get(i); // 订阅对象的subscriber属性等于传进来的subscriber if (subscription.subscriber == subscriber) { subscription.active = false; // 移除该订阅对象 subscriptions.remove(i); i--; size--; } } } } 到这,EventBus的源码基本完活啦~ 你可能感兴趣的:(源码解析EventBus的注册及事件发送) 【算法】BFS(最短路径问题、拓扑排序) 秦jh_ 算法算法数据结构c++ 个人主页:秦jh_-CSDN博客系列专栏:https://blog.csdn.net/qinjh_/category_12862161.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12862161&sharerefer=PC&sharesource=qinjh_&sharefrom=from_link目录边权为1的最短路径问题多源 简易的图书管理系统(末尾链接报告自取) 艾米莉亚小汉堡 图书信息管理系统设计一、问题描述图书信息包括:书号、书名、作者名、分类号、出版单位、出版时间、价格等。二、功能描述试设计一图书信息管理系统,使之能提供以下功能:1、系统以菜单方式工作2、图书信息录入功能(图书信息用文件保存),可不定时地增加图书信息,书号不允许重复;3、图书信息浏览功能4、图书信息查询功能查询方式(1)按书名查询(2)按作者名查询5、图书信息的删除输入书号,查询该图书,如果存在,则 Elasticsearch(ES)详解:从入门到实践 坚持蛊 elasticsearchjenkins大数据 引言简介:Elasticsearch是一个基于Lucene的分布式搜索引擎,具有高效的全文搜索功能,广泛应用于日志分析、搜索引擎、实时数据处理等领域。本文目标:介绍Elasticsearch的基本概念、架构设计、配置优化、常见应用以及实际案例,帮助开发者掌握ES1.Elasticsearch概述Elasticsearch的背景和发展历程核心功能:全文检索、分布式搜索、实时数据分析主要应用场景:日志 卷积神经网络(笔记01) 天行者@ cnn人工智能深度学习 视觉处理三大任务:分类、目标检测、图像分割CNN网络主要有三部分构成:卷积层(ConvolutionalLayer)、池化层(PoolingLayer)和激活函数一、解释卷积层中的偏置项是什么,并讨论在神经网络中引入偏置项的好处。在卷积神经网络(CNN)的卷积层里,卷积操作本质上是输入数据与卷积核(滤波器)进行逐元素相乘再求和的过程。偏置项(Bias)是一个额外的可学习参数,对于每个卷积核而言,都 Spring WebFlux:响应式编程 m0_74825223 面试学习路线阿里巴巴springjava后端 在软件开发领域,随着互联网应用的规模和复杂性不断增加,传统的编程模型逐渐暴露出一些局限性,尤其是在面对高并发、大规模数据流处理等场景时。为了应对这些挑战,响应式编程(ReactiveProgramming)应运而生,它提供了一种更为高效、灵活的编程范式,以适应不断变化的系统需求。1.SpringWebFlux简介WebFlux提供了一个非阻塞、异步的Web框架,允许开发者构建高性能、可伸缩的Web Manus被「越狱」:创始人回应风波与开源转向 UR的出不克 人工智能manusagent Manus被「越狱」:创始人回应风波与开源转向早上刷推特,一条标签为"#Manus越狱"的话题炸了。这个前些日子刚刚融了A轮的AI新贵突然成了安全圈的焦点。熬了一整晚的咖啡还没喝完,Manus团队就陷入了灭火模式。「越狱」风波:始于一条推特事情的起因很"典型"——一位ID为"AIHacker_2023"的用户前天发了条推文:"Manus的安全屏障形同虚设,两个prompt就能搞定,详情看图。"配图 MPU6050 卡尔曼滤波算法 四元数欧拉姿态解算 STM32 CubeMX HAL库 MDKkeil5 零基础移植 辛尘大海 算法stm32嵌入式硬件 文章目录一、在cubemx开启IIC并设置好对应的IIC引脚二、generatecode生成代码三、复制以下的全部代码新建分别保存放到IncSrc文件夹中1.MPU6050.h2.MPU6050.C四、如何使用总结一、在cubemx开启IIC并设置好对应的IIC引脚二、generatecode生成代码(记得生成单个c.h.文件)!!!!!!三、复制以下的全部代码新建分别保存放到IncSrc文件夹中 ES8的Java API client 8.0 简单示例操作 Elasticsearch it-shiyadi esjavaelasticsearch开发语言 1.加入依赖co.elastic.clientselasticsearch-java8.12.22.配置类@Slf4j@ConfigurationpublicclassElasticSearchConfig{@Value("${elasticsearch.hosts}")privateStringhosts;@Value("${elasticsearch.port}")privateintport INCA二次开发GUI实例化 智海行舟 python个人开发 【摘要】本文基于ETASINCA二次开发实践,深入探讨如何构建完整的自动化测试GUI系统。通过Python语言结合COM接口技术,实现从软件架构设计到功能模块开发的完整闭环,为汽车电子领域工程师提供可复用的开发范式。一、INCA二次开发技术背景1.1行业应用需求在汽车电子开发领域,ETASINCA作为行业标准标定工具,其自动化测试需求日益增长。传统的手动操作模式存在以下痛点:重复性操作耗时严重(单 【Spring】_Spring事务与事务传播机制 _周游 SpringJavaEE数据库sql 目录1.创建项目、数据库及MyBatis配置1.1创建数据库及java实体类1.2使用yml配置MyBatis1.3对应三层架构开发2.Spring编程式事务2.1编写UserController类2.2接口测试2.23关于事务回滚与事务提交的日志3.Spring声明式事务3.1编写TransController类3.2接口测试3.3关于@Transactional实现事务回滚的情况3.3.1重新 Postman怎么针对一个接口重复测试 ? 静姐说测试 自动化测试经验分享技术分享postman测试工具功能测试自动化测试软件测试测试工程师 Postman是一个常用的API测试工具,用于测试和调试接口。它提供了许多功能来让我们能够更轻松地进行接口测试,其中之一就是针对一个接口的重复测试。以下是从零到一的详细和规范的步骤来针对一个接口重复测试的文章:第一步:确定接口首先,我们需要确定要重复测试的接口。可以是一个已经存在的接口,也可以是一个新接口。确保理解接口的功能和预期的输出。第二步:创建Postman环境在开始重复测试之前,我们需要创 三维声学各向异性材料设计:具体步骤与示例 斡旋小羊 机器学习算法人工智能 三维声学各向异性材料设计:具体步骤与示例1.理论建模:三维微结构与等效参数映射(1)各向异性密度张量推导假设材料由椭球体散射体周期性嵌入基体材料构成,其等效密度张量可通过三维均匀化理论计算:未旋转椭球的局部密度张量(主轴对齐坐标系):ρell=[ρbase+f⋅Δρ⋅ab000ρbase+f⋅Δρ⋅ba000ρbase+f⋅Δρ⋅ca]\rho_{\text{ell}}=\begin{bmatri 常用图像增强算法原理及 OpenCV C++ 实现 埃菲尔铁塔_CV算法 opencv计算机视觉人工智能c++算法机器学习 一、引言图像增强是数字图像处理中的一个重要分支,其目的是改善图像的视觉效果,突出图像中的重要信息,或者将图像转换为更适合人或机器分析处理的形式。在实际应用中,图像增强技术广泛应用于医学影像、遥感图像、安防监控等领域。本文将详细介绍常用的图像增强算法原理,并给出基于OpenCVC++库的实现代码。二、图像增强算法分类图像增强算法可以分为空间域增强和频域增强两大类。空间域增强是直接对图像的像素值进行操 如何通过API用Python获取北向资金流向数据? 量化问财 量化软件QMT量化交易Python量化炒股PTradeQMT量化交易量化软件deepseek 推荐阅读:《【最全攻略】免费的量化软件有哪些?券商的交易接口怎么获取?》如何通过API用Python获取北向资金流向数据?北向资金指的是通过沪港通和深港通渠道,从香港市场流入A股市场的资金。对于投资者来说,了解北向资金流向对于把握市场趋势和投资决策具有重要意义。本文将介绍如何通过API用Python获取北向资金流向数据。理解北向资金流向数据北向资金流向数据主要包括以下几个方面:资金流入量:指通过沪 letcode hot 100 第5题 int main* letcode热题100leetcode数据结构c++算法 letcodehot100第5题题目盛最多水的容器给定一个长度为n的整数数组height。有n条垂线,第i条线的两个端点是(i,0)和(i,height[i])。找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。说明:你不能倾斜容器。示例1:输入:[1,8,6,2,5,4,8,3,7]输出:49解释:图中垂直线代表输入数组[1,8,6,2,5,4,8,3, 【新手向】从零开始学习Java(Day29)Java 网络编程 星河天欲瞩 从零开始学习Java学习java开发语言jvm网络后端 每天二十分钟,成就Java大神,点点关注不迷路!今天是第二十九天,给坚持到这里的小伙伴点个赞!对抗混乱即修行,共勉!目录网络编程基础概念Socket(套接字)ServerSocket类(服务器端)构造方法常用方法Socket类构造方法常用方法InetAddress类本地实例服务端客户端运行步骤下节预告网络编程基础概念网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。网络模 likeadmin 安装与使用指南 强和毓Hadley likeadmin安装与使用指南项目地址:https://gitcode.com/gh_mirrors/li/likeadmin目录结构及介绍在克隆或下载likeadmin项目后,你会看到以下主要目录:admin:存放所有后端管理相关的代码。controller:控制器目录,负责处理HTTP请求。model:数据模型目录,用于数据库操作。service:服务层目录,提供业务逻辑。frontend: ESP32 小智 AI 机器人入门教程从原理到实现(自己云端部署) 与光同尘 大道至简 人工智能机器人python人机交互githubvisualstudio单片机 此博客为一篇针对初学者的详细教程,涵盖小智AI机器人的原理、硬件准备、软件环境搭建、代码实现、云端部署以及优化扩展。文章结合了现有的网络资源,取长补短,确保内容易于理解和操作。简介:本教程将指导初学者使用ESP32微控制器开发一个简单的语音对话机器人“小智”。我们将介绍所需的基础原理、硬件准备、软件环境搭建,以及如何编写代码实现语音唤醒和与云端大模型的对接。通过本教程,即使没有深厚的AI或嵌入式经 我与DeepSeek读《大型网站技术架构》(5)下 诺亚凹凸曼 架构 万无一失:网站的高可用架构4.高可用的数据保证数据存储高可用的手段主要是数据备份和失效转移机制。缓存服务的高可用争论1.缓存服务需要实现高可用核心论据:避免雪崩效应:缓存宕机导致数据库瞬时压力骤增,可能引发级联故障。提升用户体验:缓存直接支撑高频访问,其不可用会导致延迟飙升、功能异常。数据热备价值:部分缓存数据(如会话信息)可能无持久化备份,丢失后影响业务连续性。适用场景:高并发实时系统:如电商秒 我与DeepSeek读《大型网站技术架构》(3) 诺亚凹凸曼 架构 大型网站架构的核心要素《大型网站技术架构:核心原理与案例分析》第三章聚焦于大型网站架构的核心要素,从技术维度剖析了构建高可用、高性能、可扩展系统的关键设计方向。1.五大核心架构要素(1)性能(Performance)目标:快速响应用户请求,优化用户体验。关键策略:前端优化:CDN加速静态资源、合并压缩JS/CSS、浏览器缓存。服务端优化:缓存(Redis/Memcached)、异步处理(消息队列) 八股文-Linux系统部分 im长街 八股文专栏linux服务器 目录权限掩码有什么作用?直到粘滞位吗?怎样将程序停留在预处理过程/编译/汇编过程后?用过gdb吗?讲讲常见的热键谈谈你对整个计算机体系的认识什么是进程?谈谈你自己的理解?进程在运行时可能会出现哪些状态?Fork函数了解多少?了解过僵尸进程和孤儿进程吗?并行和并发的区别?当发生进程切换后再次被调度时,怎样知道上次运行到哪儿了?了解过哪些环境变量什么是地址空间?和物理内存是什么关系?为什么要有它?谈谈 八股文-Linux网络部分 im长街 八股文专栏linux网络 目录TCP和UDP的区别套接字编程一般的流程是什么Cookie,session和token有什么区别HTTP和HTTPS的区别讲一下TCP的三次握手和四次挥手TCP通过什么来保证可靠性TCP通过什么方式来提高性能了解哪些TCP协议的报头数据如何解决TCP的粘包问题什么是IP协议IP协议的字段了解多少什么是网段划分WAN口ip和LAN口ip的作用了解过NAT技术吗谈一谈你对ARP协议的理解有了ip地 WordPress建站给外贸人带来的负担 小机出海 建站常谈服务器sslhttps WordPress是全球最大的开源建站平台,有着丰富的主题与插件,尽管功能非常强大,但也给想要建站的外贸人带来了一些负担。一、技术门槛与学习成本1、由于WordPress发展了几十年,里面的功能应有尽有,但往往这些复杂的功能导致建站新手对它的学习成本变得很高,需要理解各个模块与功能点,增加了上手的复杂度。2、WordPress的建站服务商他不会告诉你,你可能需要知道一些代码知识(HTML、CSS、 算法与数据结构(回文数) a_j58 数据结构 题目思路对于这个我的第一想法就是转换为字符串然后判断字符串是否为回文,它会消耗额外的地址空间。还有一种想法就是将数字反转并判断是否为回文,但可能需要处理数字溢出的问题。若要避免出现数字溢出的问题,我们可以只反转它的一半,若前半部分和后半部分相同,则说明它是一个回文数。如123321,我们将它的后半部分反转,得到123,它与前半部分相同,说明它是一个回文数。算法首先,我们可以先考虑到它的一些临界情况 Manus联创澄清:我们并未使用MCP技术 耶耶Norsea 网络杂烩人工智能 摘要近日,Manus联创针对外界关于其产品可能涉及“沙盒越狱”的疑问进行了正式回应。公司明确表示并未使用Anthropic的MCP(模型上下文协议)技术,并强调MCP是一个旨在标准化应用程序与大型语言模型(LLM)之间上下文交互的开放标准。此外,Manus联创宣布了开源计划,以增强透明度和社区参与。季逸超也确认他们没有采用MCP技术,进一步澄清了相关质疑。关键词沙盒越狱,MCP技术,开源计划,透明 Shodan的概述与安装 耶耶Norsea Shodan安全web安全python 一、Shodan简述Shodan是一个独特的网络搜索引擎,它专门针对互联网上的设备进行不间断扫描,并将扫描结果存储起来,供用户检索。这使得Shodan能够快速搜索到网络中的各种设备和服务,例如Web服务器、路由器、摄像头、物联网设备等,甚至包括某些已知漏洞的暴露设备。Shodan的主要用途:设备搜索:通过Shodan,你可以搜索到全球范围内连接到互联网的各种设备,如企业服务器、摄像头、智能家居设备 【Servlet】深入解析 Servlet 启动过程 —— 原理分析、代码实战及在 JDK 和 Spring 中的应用 工一木子 原理分析Servletjavaservlet 深入解析Servlet启动过程——原理分析、代码实战及在JDK和Spring中的应用在JavaWeb开发中,Servlet是一种用于创建动态Web应用程序的核心技术。作为JavaEE(现在是JakartaEE)的基础,Servlet在处理客户端请求、生成响应等方面发挥着重要作用。理解Servlet的启动过程,不仅能帮助我们调试和优化应用,还能为深入掌握JavaWeb开发的核心原理打下坚实基础。本文 C# 巩固记录(五) 休#威廉姆斯 C#c#开发语言 C#构造函数实例构造函数构造函数是类中特殊的成员函数,它的名称与它所在类的名称相同,并且没有返回值。当我们使用new关键字创建类的对象时,可以使用实例构造函数来创建和初始化类中的任意成员属性。静态构造函数静态构造函数用于初始化类中的静态数据或执行仅需执行一次的特定操作。静态构造函数将在创建第一个实例或引用类中的静态成员之前自动调用。静态构造函数具有以下特性:静态构造函数不使用访问权限修饰符修饰或不 手把手教你学Simulink实例:基于Simulink的三相桥式全控整流电路设计与仿真实例 小蘑菇二号 手把手教你学MATLAB专栏手把手教你学Simulink单片机嵌入式硬件matlabsimulink 目录手把手教你学Simulink实例:基于Simulink的三相桥式全控整流电路设计与仿真实例一、背景介绍二、所需工具和环境三、步骤详解步骤1:创建Simulink模型步骤1.1:打开Simulink并新建模型步骤2:添加电源模块步骤2.1:添加三相交流电源步骤3:设计三相桥式全控整流电路步骤3.1:添加可控硅模块步骤3.2:连接三相桥式全控整流电路步骤4:添加负载模块步骤4.1:添加电阻性负载步 斐波拉契数列 RichardK. c++学习 题目描述给定正整数n,求斐波那契数列的第n项F(n)。令F(n)表示斐波那契数列的第n项,它的定义是:当n=1时,F(n)=1;当n=2时,F(n)=1;当n>2时,F(n)=F(n−1)+F(n−2)。大数据版:斐波拉契数列-大数据版输入描述一个正整数n(1≤n≤104)。输出描述斐波那契数列的第n项F(n)。由于结果可能很大,因此将结果对10007取模后输出。样例1输入1输出1解释边界定义:F java封装继承多态等 麦田的设计者 javaeclipsejvmcencapsulatopn 最近一段时间看了很多的视频却忘记总结了,现在只能想到什么写什么了,希望能起到一个回忆巩固的作用。 1、final关键字 译为:最终的 & F5与集群的区别 bijian1013 weblogic集群F5 http请求配置不是通过集群,而是F5;集群是weblogic容器的,如果是ejb接口是通过集群。 F5同集群的差别,主要还是会话复制的问题,F5一把是分发http请求用的,因为http都是无状态的服务,无需关注会话问题,类似 LeetCode[Math] - #7 Reverse Integer Cwind java题解MathLeetCodeAlgorithm 原题链接:#7 Reverse Integer 要求: 按位反转输入的数字 例1: 输入 x = 123, 返回 321 例2: 输入 x = -123, 返回 -321 难度:简单 分析: 对于一般情况,首先保存输入数字的符号,然后每次取输入的末位(x%10)作为输出的高位(result = result*10 + x%10)即可。但 BufferedOutputStream 周凡杨 首先说一下这个大批量,是指有上千万的数据量。 例子: 有一张短信历史表,其数据有上千万条数据,要进行数据备份到文本文件,就是执行如下SQL然后将结果集写入到文件中! select t.msisd linux下模拟按键输入和鼠标 被触发 linux 查看/dev/input/eventX是什么类型的事件, cat /proc/bus/input/devices 设备有着自己特殊的按键键码,我需要将一些标准的按键,比如0-9,X-Z等模拟成标准按键,比如KEY_0,KEY-Z等,所以需要用到按键 模拟,具体方法就是操作/dev/input/event1文件,向它写入个input_event结构体就可以模拟按键的输入了。 linux/in ContentProvider初体验 肆无忌惮_ ContentProvider ContentProvider在安卓开发中非常重要。与Activity,Service,BroadcastReceiver并称安卓组件四大天王。 在android中的作用是用来对外共享数据。因为安卓程序的数据库文件存放在data/data/packagename里面,这里面的文件默认都是私有的,别的程序无法访问。 如果QQ游戏想访问手机QQ的帐号信息一键登录,那么就需要使用内容提供者COnte 关于Spring MVC项目(maven)中通过fileupload上传文件 843977358 mybatisspring mvc修改头像上传文件upload Spring MVC 中通过fileupload上传文件,其中项目使用maven管理。 1.上传文件首先需要的是导入相关支持jar包:commons-fileupload.jar,commons-io.jar 因为我是用的maven管理项目,所以要在pom文件中配置(每个人的jar包位置根据实际情况定) <!-- 文件上传 start by zhangyd-c --&g 使用svnkit api,纯java操作svn,实现svn提交,更新等操作 aigo svnkit 原文:http://blog.csdn.net/hardwin/article/details/7963318 import java.io.File; import org.apache.log4j.Logger; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmateso 对比浏览器,casperjs,httpclient的Header信息 alleni123 爬虫crawlerheader @Override protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String type=req.getParameter("type"); Enumeration es=re java.io操作 DataInputStream和DataOutputStream基本数据流 百合不是茶 java流 1,java中如果不保存整个对象,只保存类中的属性,那么我们可以使用本篇文章中的方法,如果要保存整个对象 先将类实例化 后面的文章将详细写到 2,DataInputStream 是java.io包中一个数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。 车辆保险理赔案例 bijian1013 车险 理赔案例: 一货运车,运输公司为车辆购买了机动车商业险和交强险,也买了安全生产责任险,运输一车烟花爆竹,在行驶途中发生爆炸,出现车毁、货损、司机亡、炸死一路人、炸毁一间民宅等惨剧,针对这几种情况,该如何赔付。 赔付建议和方案: 客户所买交强险在这里不起作用,因为交强险的赔付前提是:“机动车发生道路交通意外事故”; 如果是交通意外事故引发的爆炸,则优先适用交强险条款进行赔付,不足的部分由商业 学习Spring必学的Java基础知识(5)—注解 bijian1013 javaspring 文章来源:http://www.iteye.com/topic/1123823,整理在我的博客有两个目的:一个是原文确实很不错,通俗易懂,督促自已将博主的这一系列关于Spring文章都学完;另一个原因是为免原文被博主删除,在此记录,方便以后查找阅读。 有必要对 【Struts2一】Struts2 Hello World bit1129 Hello world Struts2 Hello World应用的基本步骤 创建Struts2的Hello World应用,包括如下几步: 1.配置web.xml 2.创建Action 3.创建struts.xml,配置Action 4.启动web server,通过浏览器访问 配置web.xml <?xml version="1.0" encoding=" 【Avro二】Avro RPC框架 bit1129 rpc 1. Avro RPC简介 1.1. RPC RPC逻辑上分为二层,一是传输层,负责网络通信;二是协议层,将数据按照一定协议格式打包和解包 从序列化方式来看,Apache Thrift 和Google的Protocol Buffers和Avro应该是属于同一个级别的框架,都能跨语言,性能优秀,数据精简,但是Avro的动态模式(不用生成代码,而且性能很好)这个特点让人非常喜欢,比较适合R lua set get cookie ronin47 lua cookie lua: local access_token = ngx.var.cookie_SGAccessToken if access_token then ngx.header["Set-Cookie"] = "SGAccessToken="..access_token.."; path=/;Max-Age=3000" end java-打印不大于N的质数 bylijinnan java public class PrimeNumber { /** * 寻找不大于N的质数 */ public static void main(String[] args) { int n=100; PrimeNumber pn=new PrimeNumber(); pn.printPrimeNumber(n); System.out.print Spring源码学习-PropertyPlaceholderHelper bylijinnan javaspring 今天在看Spring 3.0.0.RELEASE的源码,发现PropertyPlaceholderHelper的一个bug 当时觉得奇怪,上网一搜,果然是个bug,不过早就有人发现了,且已经修复: 详见: http://forum.spring.io/forum/spring-projects/container/88107-propertyplaceholderhelper-bug [逻辑与拓扑]布尔逻辑与拓扑结构的结合会产生什么? comsci 拓扑 如果我们已经在一个工作流的节点中嵌入了可以进行逻辑推理的代码,那么成百上千个这样的节点如果组成一个拓扑网络,而这个网络是可以自动遍历的,非线性的拓扑计算模型和节点内部的布尔逻辑处理的结合,会产生什么样的结果呢? 是否可以形成一种新的模糊语言识别和处理模型呢? 大家有兴趣可以试试,用软件搞这些有个好处,就是花钱比较少,就算不成 ITEYE 都换百度推广了 cuisuqiang GoogleAdSense百度推广广告外快 以前ITEYE的广告都是谷歌的Google AdSense,现在都换成百度推广了。 为什么个人博客设置里面还是Google AdSense呢? 都知道Google AdSense不好申请,这在ITEYE上也不是讨论了一两天了,强烈建议ITEYE换掉Google AdSense。至少,用一个好申请的吧。 什么时候能从ITEYE上来点外快,哪怕少点 新浪微博技术架构分析 dalan_123 新浪微博架构 新浪微博在短短一年时间内从零发展到五千万用户,我们的基层架构也发展了几个版本。第一版就是是非常快的,我们可以非常快的实现我们的模块。我们看一下技术特点,微博这个产品从架构上来分析,它需要解决的是发表和订阅的问题。我们第一版采用的是推的消息模式,假如说我们一个明星用户他有10万个粉丝,那就是说用户发表一条微博的时候,我们把这个微博消息攒成10万份,这样就是很简单了,第一版的架构实际上就是这两行字。第 玩转ARP攻击 dcj3sjt126com r 我写这片文章只是想让你明白深刻理解某一协议的好处。高手免看。如果有人利用这片文章所做的一切事情,盖不负责。 网上关于ARP的资料已经很多了,就不用我都说了。 用某一位高手的话来说,“我们能做的事情很多,唯一受限制的是我们的创造力和想象力”。 ARP也是如此。 以下讨论的机子有 一个要攻击的机子:10.5.4.178 硬件地址:52:54:4C:98 PHP编码规范 dcj3sjt126com 编码规范 一、文件格式 1. 对于只含有 php 代码的文件,我们将在文件结尾处忽略掉 "?>" 。这是为了防止多余的空格或者其它字符影响到代码。例如:<?php$foo = 'foo';2. 缩进应该能够反映出代码的逻辑结果,尽量使用四个空格,禁止使用制表符TAB,因为这样能够保证有跨客户端编程器软件的灵活性。例 linux 脱机管理(nohup) eksliang linux nohupnohup 脱机管理 nohup 转载请出自出处:http://eksliang.iteye.com/blog/2166699 nohup可以让你在脱机或者注销系统后,还能够让工作继续进行。他的语法如下 nohup [命令与参数] --在终端机前台工作 nohup [命令与参数] & --在终端机后台工作 但是这个命令需要注意的是,nohup并不支持bash的内置命令,所 BusinessObjects Enterprise Java SDK greemranqq javaBOSAPCrystal Reports 最近项目用到oracle_ADF 从SAP/BO 上调用 水晶报表,资料比较少,我做一个简单的分享,给和我一样的新手 提供更多的便利。 首先,我是尝试用JAVA JSP 去访问的。 官方API:http://devlibrary.businessobjects.com/BusinessObjectsxi/en/en/BOE_SDK/boesdk_ja 系统负载剧变下的管控策略 iamzhongyong 高并发 假如目前的系统有100台机器,能够支撑每天1亿的点击量(这个就简单比喻一下),然后系统流量剧变了要,我如何应对,系统有那些策略可以处理,这里总结了一下之前的一些做法。 1、水平扩展 这个最容易理解,加机器,这样的话对于系统刚刚开始的伸缩性设计要求比较高,能够非常灵活的添加机器,来应对流量的变化。 2、系统分组 假如系统服务的业务不同,有优先级高的,有优先级低的,那就让不同的业务调用提前分组 BitTorrent DHT 协议中文翻译 justjavac bit 前言 做了一个磁力链接和BT种子的搜索引擎 {Magnet & Torrent},因此把 DHT 协议重新看了一遍。 BEP: 5Title: DHT ProtocolVersion: 3dec52cb3ae103ce22358e3894b31cad47a6f22bLast-Modified: Tue Apr 2 16:51:45 2013 -070 Ubuntu下Java环境的搭建 macroli java工作ubuntu 配置命令: $sudo apt-get install ubuntu-restricted-extras 再运行如下命令: $sudo apt-get install sun-java6-jdk 待安装完毕后选择默认Java. $sudo update- alternatives --config java 安装过程提示选择,输入“2”即可,然后按回车键确定。 js字符串转日期(兼容IE所有版本) qiaolevip TODateStringIE /** * 字符串转时间(yyyy-MM-dd HH:mm:ss) * result (分钟) */ stringToDate : function(fDate){ var fullDate = fDate.split(" ")[0].split("-"); var fullTime = fDate.split(" 【数据挖掘学习】关联规则算法Apriori的学习与SQL简单实现购物篮分析 superlxw1234 sql数据挖掘关联规则 关联规则挖掘用于寻找给定数据集中项之间的有趣的关联或相关关系。 关联规则揭示了数据项间的未知的依赖关系,根据所挖掘的关联关系,可以从一个数据对象的信息来推断另一个数据对象的信息。 例如购物篮分析。牛奶 ⇒ 面包 [支持度:3%,置信度:40%] 支持度3%:意味3%顾客同时购买牛奶和面包。 置信度40%:意味购买牛奶的顾客40%也购买面包。 规则的支持度和置信度是两个规则兴 Spring 5.0 的系统需求,期待你的反馈 wiselyman spring Spring 5.0将在2016年发布。Spring5.0将支持JDK 9。 Spring 5.0的特性计划还在工作中,请保持关注,所以作者希望从使用者得到关于Spring 5.0系统需求方面的反馈。 按字母分类: ABCDEFGHIJKLMNOPQRSTUVWXYZ其他