14、(行为型设计模式)Java 观察者模式深度学习指南

开源至上:java前端框架排行 java基础 1.1java的8种基本数据类型装箱拆箱 1.2重写重载封装继承多态 1.3 Stack Queue 1.7 Concurrent包 1.8面向对象 1.9 String StringBuffer StringBuilder hashcode equ 1.10 java文件读取 1.11 Java反射 1.12 JDK NDK JRE JNI 1.13 static和final的区别 1.14 map, list, set区别 1.16 Session和COOKIE 1.19 10 NIO B 阅读详情

以下是为你精心撰写的 《Java 观察者模式深度学习指南》,专为 Java 后端开发者打造,内容涵盖:定义、作用、与事件驱动架构的深度对比、真实业务场景、JDK 原生实现、Spring 事件机制、Reactive 响应式演进、避坑指南、最佳实践、面试高频题,所有示例均含中文注释,可直接用于项目重构、异步解耦、消息通知、日志采集、系统监控等核心场景。


📘 Java 观察者模式深度学习指南

—— 从“主动轮询”到“事件驱动”的架构革命

作者:Java 后端架构实战导师
适用对象:Java 后端开发者(Spring Boot / 微服务 / 异步系统 / 消息队列 / 监控系统)
目标:彻底掌握“一个对象状态改变,自动通知所有依赖它的对象”的核心模式,告别“循环调用”和“紧耦合”
核心原则:“我不是通知你,我只说‘我变了’,你爱听不听。”


✅ 一、什么是观察者模式?

📌 定义:

观察者模式(Observer Pattern) 是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象(主题 / Subject)的状态发生改变时,所有依赖它的对象(观察者 / Observer)都会自动收到通知并更新。

🔍 核心思想:

  • 主题(Subject):被观察的对象,维护一个观察者列表
  • 观察者(Observer):依赖主题的对象,实现更新接口
  • 松耦合通信:主题不知道观察者是谁,只负责“通知”
  • 自动通知:主题状态变化 → 自动调用所有观察者的 update() 方法
  • 动态注册:观察者可以随时添加或移除

💡 一句话记忆:
“我不是打电话告诉你,我发个朋友圈,你关注我,自然就看到了。”

🆚 观察者模式 vs 轮询(Polling)

方式轮询(Polling)观察者模式
机制主动频繁查询“有没有变化”被动等待“有变化就通知”
效率低(即使没变化也查)高(只在变化时触发)
实时性延迟高(取决于轮询间隔)实时(变化即通知)
耦合度高(调用方知道被调用方)低(主题和观察者互不依赖)
资源消耗高(CPU、网络)低(仅触发时消耗)
典型场景旧系统、简单脚本现代系统、事件驱动

✅ 经典比喻:
你订阅了“苹果发布会”:

  • 轮询:你每分钟刷新一次官网看有没有更新 → 浪费流量和时间
  • 观察者:苹果官网发布时,自动给你发邮件/短信 → 高效、精准、及时

✅ 二、观察者模式有什么作用?(Why Use Observer Pattern?)

作用说明
✅ 实现松耦合主题和观察者完全解耦,可独立演化
✅ 支持一对多通信一个主题可通知多个观察者,无需修改主题代码
✅ 提高系统响应性状态变化立即触发,无需轮询延迟
✅ 支持广播机制一次通知,多个模块响应(如日志、缓存、通知)
✅ 支持异步解耦可将通知放入线程池、消息队列,实现异步处理
✅ 提高可扩展性新增观察者只需注册,无需修改主题
✅ 符合开闭原则新增观察者不修改主题代码
✅ 支撑事件驱动架构(EDA)是现代微服务、消息系统、响应式编程的基础

💡 经典名言:
“Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified automatically.”
——《Design Patterns: Elements of Reusable Object-Oriented Software》


✅ 三、观察者模式的典型使用场景(Java 后端真实案例)

场景说明是否推荐使用观察者模式
✅ 订单创建后发送通知创建订单 → 发短信、发邮件、记日志、更新积分✅ 强烈推荐
✅ 用户注册后激活账户注册成功 → 发验证码、发欢迎邮件、推送APP消息✅ 强烈推荐
✅ 缓存失效更新数据库更新 → 清除Redis缓存✅ 强烈推荐
✅ 系统监控告警CPU > 90% → 发钉钉、发邮件、触发自动扩容✅ 推荐
✅ 审计日志记录所有写操作 → 自动记录操作人、时间、IP✅ 推荐
✅ 数据同步主库更新 → 同步到ES、Kafka、HBase✅ 推荐
✅ 配置变更通知Nacos配置更新 → 刷新本地缓存、重启服务✅ 推荐
✅ 支付成功通知支付成功 → 更新订单状态、通知商户、发放优惠券✅ 推荐
✅ 前端WebSocket推送后端事件触发 → 推送给所有在线用户✅ 推荐
❌ 简单状态查询获取用户余额❌ 直接调用方法
❌ 同步业务调用下单 → 扣库存 → 扣库存必须同步完成❌ 用事务或同步调用
❌ 单点通知只有一个观察者,且必须同步❌ 直接调用更简单

✅ 判断标准:
“一个事件发生后,需要通知多个无关模块,且这些模块不需要立即阻塞等待?”
→ 是 → 用观察者模式!


✅ 四、观察者模式的三种实现方式详解(含中文注释)

我们从JDK 原生实现到Spring 事件机制,再到Reactive 响应式演进,逐步深入。


🔹 1. JDK 原生观察者模式(java.util.Observable + Observer)

⚠️ 注意:Observable 已过时,不推荐在新项目中使用,但理解其原理很重要。

import java.util.Observable;
import java.util.Observer;

/**
 * 【1】主题(被观察者)—— 继承 Observable
 */
class OrderService extends Observable {
    private String orderId;

    public void createOrder(String orderId) {
        this.orderId = orderId;
        System.out.println("🛒 创建订单:" + orderId);

        // ✅ 关键:通知所有观察者
        setChanged(); // 标记状态已改变
        notifyObservers(orderId); // 传递数据给观察者
    }

    public String getOrderId() {
        return orderId;
    }
}

/**
 * 【2】观察者1:发送短信
 */
class SmsObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof String orderId) {
            System.out.println("📱 发送短信:订单 " + orderId + " 已创建");
        }
    }
}

/**
 * 【3】观察者2:发送邮件
 */
class EmailObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof String orderId) {
            System.out.println("📧 发送邮件:订单 " + orderId + " 已创建");
        }
    }
}

/**
 * 【4】观察者3:记录日志
 */
class LogObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof String orderId) {
            System.out.println("📝 记录日志:订单 " + orderId + " 创建成功");
        }
    }
}

/**
 * 【5】客户端:注册观察者
 */
public class JdkObserverDemo {
    public static void main(String[] args) {
        OrderService orderService = new OrderService();

        // ✅ 注册多个观察者
        orderService.addObserver(new SmsObserver());
        orderService.addObserver(new EmailObserver());
        orderService.addObserver(new LogObserver());

        // ✅ 触发事件:自动通知所有观察者
        orderService.createOrder("ORD20240501");

        // 输出:
        // 🛒 创建订单:ORD20240501
        // 📱 发送短信:订单 ORD20240501 已创建
        // 📧 发送邮件:订单 ORD20240501 已创建
        // 📝 记录日志:订单 ORD20240501 创建成功
    }
}
✅ 优点:
  • JDK 原生支持,无需依赖
  • 简单易懂
❌ 缺点:
  • Observable 是类,不是接口 → 不支持多继承
  • notifyObservers() 会同步阻塞调用所有观察者
  • 无法传递事件类型,只能传 Object
  • 已被标记为 @Deprecated(Java 9+)

⚠️ 结论:仅用于学习,生产环境禁止使用!


🔹 2. 自定义观察者模式(推荐写法)

使用接口 + 集合实现,更灵活、更现代。

import java.util.ArrayList;
import java.util.List;

/**
 * 【1】观察者接口:定义更新方法
 */
interface OrderObserver {
    void onOrderCreated(String orderId);
}

/**
 * 【2】主题:订单服务
 */
class OrderService {
    private List<OrderObserver> observers = new ArrayList<>(); // 维护观察者列表

    public void addObserver(OrderObserver observer) {
        observers.add(observer);
    }

    public void removeObserver(OrderObserver observer) {
        observers.remove(observer);
    }

    public void createOrder(String orderId) {
        System.out.println("🛒 创建订单:" + orderId);

        // ✅ 遍历所有观察者,逐个通知
        for (OrderObserver observer : observers) {
            observer.onOrderCreated(orderId); // 通知
        }
    }
}

/**
 * 【3】观察者1:发送短信
 */
class SmsObserver implements OrderObserver {
    @Override
    public void onOrderCreated(String orderId) {
        System.out.println("📱 发送短信:订单 " + orderId + " 已创建");
    }
}

/**
 * 【4】观察者2:发送邮件
 */
class EmailObserver implements OrderObserver {
    @Override
    public void onOrderCreated(String orderId) {
        System.out.println("📧 发送邮件:订单 " + orderId + " 已创建");
    }
}

/**
 * 【5】观察者3:更新缓存
 */
class CacheObserver implements OrderObserver {
    @Override
    public void onOrderCreated(String orderId) {
        System.out.println("⚡ 清除缓存:订单 " + orderId + " 的缓存已失效");
    }
}

/**
 * 【6】客户端
 */
public class CustomObserverDemo {
    public static void main(String[] args) {
        OrderService orderService = new OrderService();

        // ✅ 注册观察者
        orderService.addObserver(new SmsObserver());
        orderService.addObserver(new EmailObserver());
        orderService.addObserver(new CacheObserver());

        // ✅ 触发事件
        orderService.createOrder("ORD20240501");

        // 输出:
        // 🛒 创建订单:ORD20240501
        // 📱 发送短信:订单 ORD20240501 已创建
        // 📧 发送邮件:订单 ORD20240501 已创建
        // ⚡ 清除缓存:订单 ORD20240501 的缓存已失效
    }
}
✅ 优点:
  • 完全自定义:可定义任意方法名、参数
  • 支持泛型:Observer<T>,类型安全
  • 支持异步:可在 onOrderCreated 中开启线程
  • 无 JDK 限制:可被多个类实现
⚠️ 缺点:
  • 同步阻塞:通知是顺序执行,慢的观察者拖慢整体
  • 无错误隔离:一个观察者异常,影响其他观察者
  • 无事件类型:一个方法处理所有事件

🔹 3. 观察者模式 + Spring 事件机制(企业级推荐)

Spring 的 ApplicationEvent + @EventListener 是观察者模式的最佳实践!

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

/**
 * 【1】自定义事件:继承 ApplicationEvent
 */
public class OrderCreatedEvent extends ApplicationEvent {
    private final String orderId;
    private final String userId;

    public OrderCreatedEvent(Object source, String orderId, String userId) {
        super(source);
        this.orderId = orderId;
        this.userId = userId;
    }

    public String getOrderId() {
        return orderId;
    }

    public String getUserId() {
        return userId;
    }
}

/**
 * 【2】主题:订单服务(发布事件)
 */
@Service
public class OrderService {

    @Autowired
    private ApplicationEventPublisher eventPublisher; // ✅ Spring 自动注入

    public void createOrder(String orderId, String userId) {
        System.out.println("🛒 创建订单:" + orderId + ",用户:" + userId);

        // ✅ 发布事件,无需知道谁监听
        eventPublisher.publishEvent(new OrderCreatedEvent(this, orderId, userId));
    }
}

/**
 * 【3】观察者1:发送短信
 */
@Component
public class SmsObserver {

    @EventListener // ✅ 自动监听 OrderCreatedEvent
    public void handleOrderCreated(OrderCreatedEvent event) {
        System.out.println("📱 发送短信:订单 " + event.getOrderId() + " 已创建");
    }
}

/**
 * 【4】观察者2:发送邮件
 */
@Component
public class EmailObserver {

    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        System.out.println("📧 发送邮件:订单 " + event.getOrderId() + " 已创建");
    }
}

/**
 * 【5】观察者3:更新缓存(异步)
 */
@Component
public class CacheObserver {

    @EventListener // ✅ 异步监听
    public void handleOrderCreated(OrderCreatedEvent event) {
        System.out.println("⚡ 清除缓存:订单 " + event.getOrderId() + " 的缓存已失效");
    }
}

/**
 * 【6】观察者4:记录审计日志(条件监听)
 */
@Component
public class AuditLogObserver {

    @EventListener(condition = "#event.userId == 'admin'") // ✅ 条件监听
    public void handleAdminOrder(OrderCreatedEvent event) {
        System.out.println("📝 审计日志:管理员 " + event.getUserId() + " 创建了订单 " + event.getOrderId());
    }
}

/**
 * 【7】启动类
 */
@SpringBootApplication
public class SpringObserverDemo {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringObserverDemo.class, args);
        OrderService orderService = context.getBean(OrderService.class);

        // ✅ 触发事件:自动通知所有监听者
        orderService.createOrder("ORD20240501", "user123");
        orderService.createOrder("ORD20240502", "admin");

        // 输出:
        // 🛒 创建订单:ORD20240501,用户:user123
        // 📱 发送短信:订单 ORD20240501 已创建
        // 📧 发送邮件:订单 ORD20240501 已创建
        // ⚡ 清除缓存:订单 ORD20240501 的缓存已失效
        //
        // 🛒 创建订单:ORD20240502,用户:admin
        // 📱 发送短信:订单 ORD20240502 已创建
        // 📧 发送邮件:订单 ORD20240502 已创建
        // ⚡ 清除缓存:订单 ORD20240502 的缓存已失效
        // 📝 审计日志:管理员 admin 创建了订单 ORD20240502
    }
}
✅ 优点:
  • 完全解耦:发布者和监听者无直接依赖
  • 注解驱动:@EventListener 自动注册
  • 支持异步:加 @Async 实现异步通知
  • 支持条件监听:condition = "#event.userId == 'admin'" 灵活过滤
  • 支持泛型事件:可定义复杂事件结构
  • 支持事务同步/异步:@EventListener(phase = Phase.AFTER_COMMIT) 等
  • Spring 官方推荐:所有 Spring Boot 项目都在用!
⚠️ 注意:
  • 默认是同步阻塞:监听者方法执行慢,会拖慢主线程
  • 异步监听需加 @EnableAsync 和 @Async

✅ 开启异步监听:

@SpringBootApplication
@EnableAsync // ✅ 启用异步支持
public class SpringObserverDemo { ... }

@Component
public class CacheObserver {
    @Async // ✅ 异步执行
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 非阻塞,不影响订单创建流程
        System.out.println("⚡ 异步清除缓存:" + event.getOrderId());
    }
}

🔹 4. 观察者模式 + Reactor 响应式演进(现代 Java)

在高并发、流式处理场景下,使用 Reactor 替代传统观察者。

import reactor.core.publisher.Flux;
import reactor.core.publisher.FluxSink;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 【1】主题:订单流
 */
public class OrderStream {
    private final Flux<String> orderFlux;

    public OrderStream() {
        AtomicLong counter = new AtomicLong(0);
        this.orderFlux = Flux.create(emitter -> {
            while (true) {
                long id = counter.incrementAndGet();
                emitter.next("ORD" + id); // 发送事件
                try {
                    Thread.sleep(1000); // 模拟每秒生成一个订单
                } catch (InterruptedException e) {
                    emitter.error(e);
                    break;
                }
            }
        });
    }

    public Flux<String> getOrderStream() {
        return orderFlux;
    }
}

/**
 * 【2】观察者1:短信通知
 */
class SmsObserver {
    public void subscribeTo(OrderStream stream) {
        stream.getOrderStream()
              .subscribe(orderId -> System.out.println("📱 发送短信:" + orderId));
    }
}

/**
 * 【3】观察者2:日志记录
 */
class LogObserver {
    public void subscribeTo(OrderStream stream) {
        stream.getOrderStream()
              .subscribe(orderId -> System.out.println("📝 记录日志:" + orderId));
    }
}

/**
 * 【4】客户端
 */
public class ReactiveObserverDemo {
    public static void main(String[] args) throws InterruptedException {
        OrderStream stream = new OrderStream();

        // ✅ 注册观察者(订阅者)
        new SmsObserver().subscribeTo(stream);
        new LogObserver().subscribeTo(stream);

        // 运行10秒
        Thread.sleep(10000);
    }
}
✅ 优点:
  • 背压(Backpressure):消费者慢时,生产者自动降速
  • 非阻塞、高并发:基于响应式流(Reactive Streams)
  • 支持链式操作:filter()、map()、flatMap()
  • 现代 Java 标准:Spring WebFlux、RSocket、Kafka Streams 都基于此
⚠️ 缺点:
  • 学习曲线陡峭
  • 适用于高吞吐、流式系统,普通业务不必要

✅ 五、观察者模式 vs 事件驱动架构(EDA)对比

维度观察者模式事件驱动架构(EDA)
范围单进程内跨服务、跨系统
通信方式方法调用消息队列(Kafka/RabbitMQ)
耦合度低极低(完全解耦)
可靠性同步,可能丢失持久化、重试、确认
扩展性有限无限(可横向扩展)
典型场景单体应用内通知微服务、分布式系统
实现@EventListener@KafkaListener、@RabbitListener

✅ 演进关系:
观察者模式 → Spring 事件 → 消息队列(Kafka)
本质都是“发布-订阅”思想,只是通信范围和可靠性不同


✅ 六、观察者模式的避坑指南(Java 后端高频踩坑)

问题原因解决方案
❌ 同步阻塞导致性能差观察者方法执行慢,拖慢主线程✅ 使用 @Async 异步处理
❌ 异常导致通知中断一个观察者抛异常,其他不执行✅ 每个监听器加 try-catch,或使用 @EventListener 的 fallback
❌ 内存泄漏观察者未注销✅ 在 @PreDestroy 或 DisposableBean 中 removeObserver()
❌ 事件循环依赖A 发事件 → B 处理 → B 发事件 → A 处理✅ 设计时避免循环依赖,用事件版本号或去重
❌ 事件命名混乱OrderEvent、OrderCreatedEvent、OrderCreateEvent✅ 统一命名规范:{Entity}{Action}Event
❌ 事件数据过大传递整个对象,序列化开销大✅ 只传递必要字段(ID、类型)
❌ 用观察者做同步业务如“扣库存”必须同步完成✅ 用事务或同步调用,观察者只做异步事后处理

✅ 七、学习建议与进阶路径

阶段建议
📚 第一周将你项目中“订单创建后发短信、发邮件”的 if-else 重构为 Spring 事件
📚 第二周用 @EventListener 实现“缓存自动清除”、“审计日志自动记录”
📚 第三周用 @Async + @EventListener 实现异步通知,提升接口响应速度
📚 第四周阅读 Spring 源码:ApplicationEventMulticaster 如何实现事件分发?
📚 面试准备准备回答:

“你项目中哪里用了观察者模式?”
“Spring 的 @EventListener 是观察者模式吗?”
“观察者模式和策略模式区别?”
“如何解决观察者模式中的异步和异常问题?” |


✅ 八、观察者模式面试高频题(附答案)

Q1:观察者模式解决了什么问题?

A:解决了“一个对象状态变化,需要通知多个依赖对象”的问题,实现松耦合、自动通知。

Q2:Spring 的 @EventListener 是观察者模式吗?

A:是的!它是观察者模式在 Spring 框架中的注解化实现,发布者发布事件,监听者通过 @EventListener 自动订阅。

Q3:观察者模式和策略模式的区别?

A:

  • 观察者:“我变了,通知你们”(一对多)
  • 策略:“你选哪个算法”(一对一,客户端选择)
    → 一个是“广播”,一个是“选择”

Q4:如何解决观察者模式中的性能问题?

A:

  1. 使用 @Async 实现异步通知
  2. 每个监听器加 try-catch 防止异常中断
  3. 只传递必要数据,避免序列化大对象
  4. 使用消息队列(Kafka)实现跨进程解耦

Q5:什么时候不该用观察者模式?

A:

  • 通知必须同步完成(如扣库存)
  • 只有一个观察者,且必须立即执行
  • 性能要求极高,且事件频率极低(直接调用更简单)

✅ 九、总结:观察者模式选型决策树

graph TD
    A[需要一个事件触发多个响应吗?] --> B{是否在同一进程?}
    B -->|是| C{是否需要异步?}
    C -->|是| D[用 @Async + @EventListener]
    C -->|否| E[用 @EventListener]
    B -->|否| F[用 Kafka/RabbitMQ 实现事件驱动]

✅ 最终推荐:

  • 单体应用、异步通知 → ✅ Spring @EventListener + @Async(最优雅)
  • 微服务、跨系统 → ✅ Kafka / RabbitMQ(最可靠)
  • 高并发流式处理 → ✅ Reactor / RxJava(最现代)
  • 绝对不要:JDK Observable、同步阻塞通知、循环依赖

✅ 十、结语:真正的高手,不通知别人,只发布一个信号

你不是在学“观察者模式”,你是在学“如何让系统各模块自主响应,而非被动等待”。

✅ 当你看到订单创建后,短信、邮件、缓存、日志、积分、风控自动全部触发,而你只写了一行 publishEvent() 时,你已经掌握了事件驱动的精髓。
✅ 当你用 Kafka 实现“支付成功”事件,让 5 个微服务各自消费,互不影响时,你已经是分布式架构师了。

不要为了“用模式”而用模式,
要为了“系统可扩展、可解耦、可响应”而选择它。


Java基础知识 1 Java开发环境 1.1 Java语言特点 简单性 高性能 编译性 解释性 面向对象 分布式处理 健壮性 安全性 开源 跨平台 什么是跨平台性? 通过Java语言编写的应用程序在不同的系统平台上都可以运行。 原理是什么? 只要在需要运行java应用程序的操作系统上,先安装一个Java虚拟机(JVM Java Virtual Machine)即可。由JVM来负责Java程序在该系统中的运行。 因为有了JVM,所以同一个Java程序在三个不同的操作系统中都可以执行。这样就实现了Java程序的跨平台性 阅读详情

相关推荐

System Verilog学习笔记(十九)——覆盖率

覆盖率是用来衡量验证精度和完备性的数据指标。也可以告诉我们在仿真时设计的哪些结构被触发,哪些没被触发。高质量的验证需要满足以下三个条件。

ljy77882333的博客 2142

CLIP-GmP-ViT-L-14助力Java面试:图解常见设计模式与代码意图匹配

本文介绍了如何利用星图GPU平台,一键自动化部署CLIP-GmP-ViT-L-14图文匹配测试工具,以创新方式辅助Java面试。该工具通过计算设计模式标准图示与候选人代码意图描述之间的语义相似度,为评估其对设计模式的理解提供客观、可量化的参考,从而提升面试评估的效率和精准度。

weixin_35871529的博客 26

告别混乱!用Cadence Capture CIS高效管理你的原理图库:以单逻辑器件K9F2G08U0M为例

本文以单逻辑器件K9F2G08U0M为例,详细介绍了如何使用Cadence Capture CIS高效管理原理图库。通过三级分类体系、工程化命名规范和智能检索技术,帮助工程师实现从混乱到有序的转变,提升团队协作效率和设计准确性。

aizhi0169的博客 398

JAVA设计模式类第一博主,用这份文档覆盖GOF研磨这23种设计模式(2)

由于关于设计的知识过于博大精深,因此本书“集中火力”,重点讲述GoF著作中涉及的23个设计模式本身,以及和这些设计模式相关的应用内容。本书的示例虽然大都来自实际应用,但是经过相当的删除简化和重新组合:另外一点,为了突出设计模式这个主题,因此代码并不是按照实际应用那样来严格要求,很多例外处理、数据检测等都没有做,逻辑也未见得那么严密:还有一点, 在实际的开发中,很可能是多个模式组合来实现某个功能,但是本书为了示例某个模式,让重点突出而避免读者迷惑,会选择重点示例某个模式的用法,而简化或去掉其他模式。

2401_84910888的博客 900

【可信数据空间-连接器技术架构设计方案】

一句话概括连接器是可信数据空间的“数据保镖”和“外交官”。连接器就是一个部署在你本地的软件代理,它代表你安全地对外提供数据服务,确保在共享数据价值的同时,牢牢守住数据的所有权和控制权。它是实现“数据可用不可见”这一理想的关键技术部件。一个生动的比喻:银行的金库和接待员想象一下,你的数据就是藏在银行金库里的黄金和钞票。金库(你的内部数据库): 绝对安全,外人绝对不能进。接待员(连接器): 坐在银行大厅里,负责与客户打交道。客户向接待员提出请求:“我想取1000元。

u014716614的博客 2264

线上专利申请(超详细)| 签名确认

在【法人登录】页面点击【证书登录】按钮,弹出证书登录提示框,点击【确 认】按钮,进入到输入证书密码页面,点击【取消】按钮,取消本次操作。企业在提交申请时,需要增加签名,如使用企业账户点击提交,会弹出“法人、代理机构不能签名,请使用经办人签名”,这个时候就需要换个账号了。在需要签名时,将专利官网的登录方式点击法人登录,选择扫码登录,使用移动端经办人账户的扫一扫功能扫描登录。登录完成后,再点击签名,使用移动端扫一扫功能,扫描签名,输入证书号,确认签名,并提交。最后,祝大家的申请都成功!

weixin_62112323的博客 9108

深度学习!刚毕业2年就拿到阿里的offer,分享我的阿里4面面经!

一点心里话 如果你今天还在问我“程序员为什么需要深度学习?”,那么这只是意味着你对开发的兴趣并不高,你对编程的热情并不够,你对自己的职业发展也没有一个清晰的规划。 作为开发人员来说,不说要求自己成为业内顶尖,但也要保证自己不被市场所淘汰,学习对于程序员来说是最基本的事情。 一面 1.自我介绍,包括做过项目。 2.有看过哪些JDK源码,了解哪些常用库。 3.集合框架HashMap的扩容机制,ConcurrnetHashMap的原理 4.jvm内存模型与gc内存回收机制 5.classloader结构,是否可以

weixin_53170684的博客 315

基于SiamFC的红外目标跟踪

初始化阶段:在第一帧中,通过用户标注获得目标框,从目标区域中提取一个固定大小的模板(称为 exemplar)。搜索阶段:在后续帧中,在以当前目标中心为中心的较大区域(称为 instance)内进行搜索,将模板与搜索区域通过卷积操作得到响应图。位置更新:在响应图中找到峰值位置,并转换到原图坐标,用以更新目标中心。部分实现中还会考虑多尺度搜索和目标尺寸更新。import cv2# 定义 SiamFC 简易网络(示例)# 特征提取部分,注意红外图像通常为单通道,使用较少的卷积核数提高实时性。

weixin_43745234的博客 774

如何深入学习?Android中高级进阶书籍推荐

详细讲解原理、概念、专项工具使用的场景和对应的使用方法,同时提炼总结不同类型的性能缺陷和对应的排查手段、定位方法和解决方案,还会帮助读者从全新的角度学习如何应对专项测评要面对的两个基础问题:UI 自动化测试和竞品测试。书中给出了70 多个可行的重构,每个重构都介绍了一种经过验证的代码变换手法的动机和技术。本书的作者是来自腾讯 SNG 专项测试团队的工程师们,他们负责手机 QQ、QQ 空间、QQ 音乐等的性能评测与优化工作,在 App 的资源类性能、交互类性能的分析与优化上挖掘很深,累积了不少案例和经验。

2401_84123171的博客 916

解决此平台不支持虚拟化的 Intel VT-x/EPT故障问题

当我们在VMware Workstation虚拟机上【启用】虚拟系统(如:Windows10)所在的虚【拟机设置】【处理器】【虚拟化引擎】下面的【虚拟化 Intel VT-x/EPT 或AMD-V/RVI(V)】内容后,在启动虚拟系统时,虚拟系统无法启动,且弹出【此平台不支持虚拟化的 Intel VT-x/EPT。不使用虚拟化的 Intel VT-x/EPT,是否继续】窗口

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 1万+

Xilinx FPGA资源解析与使用系列——Transceiver(六)关键时钟梳理之TXOUTCLK和RXOUTCLK

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Xilinx FPGA资源解析与使用系列——Transceiver(六)transceiver内部关键时钟梳理之TXOUTCLK和RXOUTCLK前言TXOUTCLKRXOUTCLK 前言 前面我们已经研读了 transceiver的参考时钟 和复位的相关内容。 但是随着内容的深入,越来越多的信号出现在我的面前。 例如 TXOUTCLK、TXUSERCLK、TXUSERCLK2 RXOUTCLK、RXUSERCLK、RXUSERCLK2

gzy0506的博客 8085

GitHub上非常实用的40个开源JAVA项目_java开源项目

29.spring-projects/spring-loaded:spring开源的一个热替换插件,运行时监听class文件的变更并执行transform。40.weixin-java-tools:可能是目前最好最全的微信Java开发工具包,支持包括微信支付、开放平台、小程序、企业号和公众号等的开发。9.socketio/socket.io-client-java:http://Socket.IO的Netty实现(做聊天室可以用)。

2401_87252283的博客 2231

【WRF后处理】基于wrf-python处理wrf运行结果wrfout_d01

基于wrf-python处理wrf运行结果wrfout_d01

WW、forever的博客 5207

总结——》【Java】

java

小仙~ 2730

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

深度学习毕设项目:用于COVID-19检测的轻量级深度学习模型实现

主要内容:免费开题报告、任务书、全bao定制+中期检查PPT、代码编写、🚢文编写和辅导、🚢文降重、长期答辩答疑辅导、一对一专业代码讲解辅导答辩、模拟答辩演练、和理解代码逻辑思路。

2501_91703032的博客 903

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Java学习路线总结(书籍、视频推荐篇)_亿级流量java高并发与网络编程实战pdf下载(1)

附上我的书架,《Java编程思想》读了两遍,《深入理解Java虚拟机》读了一遍,《Head First设计模式》读了一遍,《Java并发编程实战》读了一遍,《重构》读了一遍,《Spring实战》没看进去,《Effective Java》读了一遍,《软技能 代码之外的生存指南》读了一遍,《深入理解Java虚拟机第三版》,《微服务实战》《算法4》,《亿级流量Java高并发与网络编程实战》,《JavaScript高级程序设计》,《HTTP权威指南》,《Java性能优化实践》还没开封。

2401_84573307的博客 1289

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

程序员为什么需要一直深度学习?我用我的阿里四面告诉你答案(本人已offer)

前言 首先作为开发人员来说,不说要求自己成为业内顶尖,但也要保证自己不被市场所淘汰,学习对于程序员来说是最基本的事情。我个人认为,程序员就是一个需要不断深度学习的职业,下面是我根据我的面试总结出来的一点经验和面试真题,希望对你们有帮助! 阿里一面 1 ,自我介绍 2,说说有哪几种数据结构,每一种具体说说在哪能用到 3,说说进程和线程的区别 4,说说进程之间通信,每一种具体说说 5,说说进程的死锁条件,如何解决死锁 6,说说数据库的事物7,事物的隔离级别 8,了解redis 么 9,mysql 的两种引擎 1

欢迎您访问我的公众号【前程有光】 783

Java工程师30天转型AI开发实战指南

在当今技术融合趋势下,掌握AI开发能力已成为开发者进阶的关键路径。从技术原理来看,机器学习框架如PyTorch和TensorFlow通过张量运算和自动微分系统实现模型训练,其底层与Java开发者熟悉的并发编程和设计模式存在思维映射。工程实践中,环境配置、依赖管理等传统技能可直接迁移至AI项目,而向量化运算和模型部署等新技能则需重点突破。对于有Java背景的开发者,转型AI开发可充分发挥既有工程化优势,快速掌握PyTorch框架和Transformer模型等核心技术,应用于智能客服、推荐系统等实际场景。本指南

weixin_30279671的博客 330

2024年阿里+头条+腾讯大厂Android笔试真题,37岁程序员被裁

自我介绍一下,小编13年北京科技大学毕业,曾经在字节跳动待过,也去过vivo、小米等大厂,18年进入华为一直到现在。小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担,能在岗位上再创辉煌,步步高升!!。

2401_84898679的博客 1087

Java 面试进阶攻略:7 大技能 +12 份进阶笔记 + 面试 150 题

以下都是阿里大牛推荐的主流技术,当你全部掌握上述的这些技术那么你就已经是 P8 级别,而且你也已经形成了自己的体系,当更加新潮的技术出来时那么你自己稍微花点时间就能吃透,毕竟那时候你已经不是以前的那个你了, 懂底层原理,知道性能特征,以及功能,想要弄懂新的技术那么也不会太吃力。希望这些能对你的架构师成长之路,起到一定的帮助,文末还准备许多架构进阶学习资料,可获取。JVM 优化,Java 程序优化,tomcat 优化,Linux 优化,SQL 优化等。堆,栈,队列,hash,链表等。单例模式,建造者模式。

fuladulu的博客 45

火爆豆瓣,GitHub 10,java校招面试经验

谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)66个Java面试知识点架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)算法刷题(PDF)

2401_84435885的博客 572

GitHub上非常实用的40个开源JAVA项目

1.biezhi/blade:一款轻量级、高性能、简洁优雅的MVC框架。 GitHub:http://h5ip.cn/O975 2.scribejava/scribejava:一个简单的 Java 实现的 OAuth/OAuth2 库。 GitHub:http://h5ip.cn/0pNf 3.winterbe/java8-tutorial:绝对值得一看的Java8指南、教程。 GitHub:http://h5ip.cn/W6du 4.javaee-samples/javaee...

【优快云】 1427

从数学到深度学习的学习资料及教程合集

教程合集

诸神缄默不语的博客 5047

程序员 各种PDF格式电子书--免费网盘资源

-请妥善保存,后期还会有更多更新,如果读者有不同的书籍资源或者这里没有你要找的书籍,也可以直接评论,我在这里添加-- 如果有不存在的链接或者失效的,直接私信我或者在下方评论 所有的數據链接:链接:https://pan.baidu.com/s/1sW6Yu2qno5N3HpVUjGdZJg 密码:1ego 需要的直接自取 *******2018/7/23 已更新320 本***...

weixin_30550081的博客 3301

【Java转AI实战】第1讲:Java工程师的AI转型地图——你70%的技能已经够用了

本文是**「Java转AI实战」系列**的第1讲,共16讲。本系列专为3年以上Java后端工程师设计,用你熟悉的Spring Boot、设计模式、MyBatis类比来讲解AI应用开发,不需要任何AI/机器学习基础。

码农飞哥 420
上一篇: 13、(行为型设计模式)Java 模板方法模式深度学习指南
下一篇: 15、(行为型设计模式)Java 责任链模式深度学习指南
龙茶清欢
博客等级 码龄7年 3720粉丝 375原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值