前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >并发设计模式实战系列(10):Balking(犹豫模式)

并发设计模式实战系列(10):Balking(犹豫模式)

作者头像
摘星.
发布于 2025-05-20 06:49:03
发布于 2025-05-20 06:49:03
8900
代码可运行
举报
文章被收录于专栏:博客专享博客专享
运行总次数:0
代码可运行
🌟 大家好,我是摘星! 🌟

今天为大家带来的是并发设计模式实战系列,第10章Balking(犹豫模式),废话不多说直接开始~

一、核心原理深度拆解

1. 状态守护机制
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
┌───────────────┐       ┌───────────────┐
│   Client      │──────>│   GuardedObj   │
└───────────────┘       ├───────────────┤
                         │ - state       │
                         │ - checkState()│
                         │ - changeState() 
                         └───────────────┘
  • 状态检查:通过原子操作验证对象是否处于可处理状态
  • 条件拦截:当状态不满足时立即放弃操作(Balking)
  • 线程安全:所有状态变更必须加锁(synchronized或CAS)
2. 与状态模式的区别
  • Balking:直接放弃不符合条件的请求(快速失败)
  • State Pattern:将行为委托给不同状态对象处理

二、生活化类比:自动售货机

系统组件

现实类比

核心行为

Client

顾客投币

发起购买请求

checkState

货品检测系统

检查库存和金额是否充足

Balking

退币机制

条件不满足时立即退币

  • 典型场景:当检测到「缺货」或「金额不足」时,立即终止交易流程

三、Java代码实现(生产级Demo)

1. 完整可运行代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.concurrent.atomic.*;

// 带Balking模式的文件自动保存
public class AutoSaveEditor {
    // 状态标记(原子操作)
    private final AtomicBoolean changed = new AtomicBoolean(false);
    private final AtomicInteger autoSaveCount = new AtomicInteger(0);
    
    // 状态守护方法
    public void autoSave() {
        // STEP 1: 状态检查
        if (!changed.getAndSet(false)) {
            System.out.println("[Balking] 无修改不保存");
            return; // 快速返回
        }
        
        // STEP 2: 实际保存操作
        doSave();
    }
    
    // 修改内容后触发状态变更
    public void editDocument(String newContent) {
        System.out.println("编辑内容: " + newContent);
        changed.set(true);
    }
    
    private void doSave() {
        System.out.println("自动保存第" + autoSaveCount.incrementAndGet() + "次...");
        // 模拟IO操作
        try { Thread.sleep(500); } 
        catch (InterruptedException e) {}
    }
    
    // 测试用例
    public static void main(String[] args) throws InterruptedException {
        AutoSaveEditor editor = new AutoSaveEditor();
        
        // 第一次修改(应触发保存)
        editor.editDocument("Version1");
        editor.autoSave();
        
        // 连续修改不保存(状态被消费)
        editor.editDocument("Version2");
        editor.editDocument("Version3");
        editor.autoSave(); // 只会保存一次
        
        // 无修改情况
        editor.autoSave();
    }
}
2. 关键实现技术
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 1. 原子状态标记
private final AtomicBoolean changed = new AtomicBoolean(false);

// 2. 状态检查与重置一体化操作
changed.getAndSet(false) 

// 3. 线程安全计数器
autoSaveCount.incrementAndGet()

四、横向对比表格

1. 相似模式对比

模式

核心策略

适用场景

Balking

条件不满足立即放弃

状态校验场景(如自动保存)

Retry

条件不满足循环重试

网络请求等可恢复场景

State

委托给状态对象处理

复杂状态转换场景

Guard Suspension

等待条件满足

必须完成的阻塞任务

2. 线程安全方案选择

实现方式

优点

缺点

synchronized

简单可靠

性能开销较大

AtomicXXX

无锁高性能

只适用于简单状态

ReentrantLock

可中断/超时

需手动释放锁

volatile

轻量级可见性保证

不保证复合操作原子性


五、高级应用技巧

1. 组合模式增强
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 结合Guard Suspension模式实现超时控制
public boolean autoSaveWithTimeout(long timeout) throws InterruptedException {
    long start = System.currentTimeMillis();
    while (!changed.get()) {
        if (System.currentTimeMillis() - start > timeout) {
            return false; // 超时放弃
        }
        Thread.sleep(50);
    }
    return doSave();
}
2. 日志增强实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 记录Balking事件
if (!changed.get()) {
    auditLogger.log("Balking at " + LocalDateTime.now());
    return;
}
3. Spring应用场景
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class ConfigMonitor {
    @Scheduled(fixedRate = 5000)
    public void reloadConfig() {
        if (!GlobalConfig.isDirty()) {
            return; // Balking
        }
        // 重新加载配置...
    }
}

好的!我将延续原有结构,从 第六部分 开始扩展Balking模式的深度内容,保持技术解析的连贯性和完整性。


六、Balking模式变体与扩展(续)

1. 分布式场景下的Balking
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 使用Redis实现分布式状态标记
public class DistributedBalking {
    private final Jedis jedis;
    private static final String LOCK_KEY = "resource:lock";

    public boolean tryProcess(String resourceId) {
        // SETNX实现原子状态检查(分布式锁原理)
        Long result = jedis.setnx(LOCK_KEY, "locked");
        if (result == 0) {
            System.out.println("[Distributed Balking] 资源已被占用");
            return false;
        }
        jedis.expire(LOCK_KEY, 30);
        return true;
    }
}

关键点

  • 使用RedisSETNX命令替代本地原子变量
  • 需设置过期时间避免死锁
  • 适用于微服务抢单、定时任务调度等场景
2. 分级Balking策略
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 根据业务重要性实现分级放弃
public class PriorityBalking {
    private enum Priority { HIGH, NORMAL, LOW }
    
    public void process(Priority priority) {
        if (!checkResource()) {
            if (priority == Priority.LOW) {
                System.out.println("低优先级任务放弃");
                return;
            }
            // 高优先级任务等待资源
            waitForResource();
        }
        // 执行处理...
    }
}

七、性能优化与陷阱规避

1. 状态检查的性能优化

优化手段

实现方式

适用场景

双重检查锁

先非阻塞检查,再同步块内二次检查

高并发读场景

状态标记分组

对不同资源分桶标记

多资源竞争场景

延迟状态重置

处理完成后再重置状态(减少CAS竞争)

短时高频状态变更

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 双重检查锁实现示例
public class DoubleCheckBalking {
    private volatile boolean busy = false;
    
    public void execute() {
        if (!busy) {  // 第一次非阻塞检查
            synchronized (this) {
                if (!busy) {  // 第二次原子检查
                    busy = true;
                    // 执行任务...
                    busy = false;
                }
            }
        }
    }
}
2. 常见陷阱与解决方案

陷阱现象

根本原因

解决方案

活锁(Livelock)

多个线程持续检查-放弃循环

引入随机退避时间

状态逃逸

对象引用被外部修改

防御性拷贝(Deep Copy)

监控缺失

无法追踪放弃操作次数

添加Metrics计数器


八、工业级应用案例

1. Tomcat连接器中的Balking
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// org.apache.tomcat.util.net.AbstractEndpoint
public boolean processSocket(SocketWrapperBase<S> socket) {
    if (running && !paused) {
        // 将socket交给线程池处理
        return executor.execute(new SocketProcessor(socket));
    }
    // 服务未运行立即放弃
    return false; 
}

设计启示

  • 通过runningpaused双状态判断
  • 放弃时直接关闭Socket连接释放资源
2. 电商库存扣减场景
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class InventoryService {
    private final AtomicInteger stock = new AtomicInteger(100);

    public boolean deductStock(int quantity) {
        int current = stock.get();
        if (current < quantity) {
            // 库存不足立即返回
            metrics.log("balking:insufficient_stock"); 
            return false;
        }
        // CAS原子扣减
        return stock.compareAndSet(current, current - quantity);
    }
}

九、与其他模式的组合应用

1. Balking + Observer 模式
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ConfigMonitor {
    private final List<Listener> listeners = new CopyOnWriteArrayList<>();
    private volatile String currentConfig;

    // 配置变更通知(Balking条件检查)
    public void updateConfig(String newConfig) {
        if (Objects.equals(currentConfig, newConfig)) {
            return; // 配置未变化时放弃
        }
        this.currentConfig = newConfig;
        notifyListeners();
    }
}
2. Balking + Chain of Responsibility
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public abstract class OrderHandler {
    private OrderHandler next;

    public void handle(Order order) {
        if (canHandle(order)) {
            // 实际处理逻辑...
        } else if (next != null) {
            next.handle(order);
        } else {
            // 责任链终止时的Balking
            order.fail("NO_HANDLER_FOUND");
        }
    }
    protected abstract boolean canHandle(Order order);
}

十、终极对比表格:Balking模式家族

变体名称

核心差异点

典型应用场景

Java SDK中的体现

经典Balking

基于本地原子变量

单机资源控制

AtomicBoolean.getAndSet

分布式Balking

依赖外部存储状态

跨服务协调

Redis SETNX

分级Balking

按优先级差异化处理

业务流量分级

ThreadPoolExecutor拒绝策略

延迟Balking

超时后才放弃

弱依赖服务调用

Future.get(timeout)

批量Balking

累积多个请求后统一判断

批量处理系统

BufferedWriter.flush

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-04-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、核心原理深度拆解
    • 1. 状态守护机制
    • 2. 与状态模式的区别
    • 二、生活化类比:自动售货机
    • 三、Java代码实现(生产级Demo)
      • 1. 完整可运行代码
      • 2. 关键实现技术
    • 四、横向对比表格
      • 1. 相似模式对比
      • 2. 线程安全方案选择
    • 五、高级应用技巧
      • 1. 组合模式增强
      • 2. 日志增强实现
      • 3. Spring应用场景
    • 六、Balking模式变体与扩展(续)
      • 1. 分布式场景下的Balking
      • 2. 分级Balking策略
    • 七、性能优化与陷阱规避
      • 1. 状态检查的性能优化
      • 2. 常见陷阱与解决方案
    • 八、工业级应用案例
      • 1. Tomcat连接器中的Balking
      • 2. 电商库存扣减场景
    • 九、与其他模式的组合应用
      • 1. Balking + Observer 模式
      • 2. Balking + Chain of Responsibility
    • 十、终极对比表格:Balking模式家族
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档