go:Condition Variable Pattern

项目结构:

Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Condition Variable  Pattern  条件变量模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/10 20:37
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : logger.go
*/
package logger
 
import (
    "log"
    "os"
)
 
type Logger struct {
    *log.Logger
}
 
func NewLogger() *Logger {
    return &Logger{
        Logger: log.New(os.Stdout, "[Jewelry-System] ", log.LstdFlags|log.Lmsgprefix),
    }
}
Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Condition Variable  Pattern  条件变量模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/10 20:38
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : config.go
*/
package config
 
// SystemConfig 生产质检系统统一配置(可扩展:DB、MQ、限流等)
type SystemConfig struct {
    BoxCapacity    int // 珠宝箱容量
    WorkerCount    int // 工匠数量
    InspectorCount int // 质检员数量
    ProduceCount   int // 每人生产数量
    CheckCount     int // 每人质检数量
}
 
// DefaultConfig 默认生产配置
func DefaultConfig() *SystemConfig {
    return &SystemConfig{
        BoxCapacity:    2,
        WorkerCount:    2,
        InspectorCount: 2,
        ProduceCount:   3,
        CheckCount:     3,
    }
}
  
Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Condition Variable  Pattern  条件变量模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/10 20:38
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : jewelry_box.go
*/
package service
 
import (
    "godesginpattern/conditionvariable/common/logger"
    "godesginpattern/conditionvariable/domain"
    "sync"
)
 
// JewelryBoxService 珠宝箱服务
// 单一职责:仅封装 条件变量 + 并发安全存取
type JewelryBoxService struct {
    mu      sync.Mutex
    cond    *sync.Cond
    storage []*domain.Jewel
    maxCap  int
    logger  *logger.Logger
}
 
// NewJewelryBoxService 创建服务实例
func NewJewelryBoxService(maxCap int, log *logger.Logger) *JewelryBoxService {
    s := &JewelryBoxService{
        maxCap: maxCap,
        logger: log,
    }
    s.cond = sync.NewCond(&s.mu) // 绑定锁
    return s
}
 
// Put 放入珠宝(生产者用)
func (s *JewelryBoxService) Put(j *domain.Jewel) error {
    s.mu.Lock()
    defer s.mu.Unlock()
 
    // 等待:箱子未满
    for len(s.storage) >= s.maxCap {
        s.logger.Printf("珠宝箱已满,工匠[%d]等待 | 容量:%d/%d", j.WorkerID, len(s.storage), s.maxCap)
        s.cond.Wait()
    }
 
    s.storage = append(s.storage, j)
    s.logger.Printf("工匠[%d]放入珠宝:%s | 库存:%d/%d", j.WorkerID, j.ID, len(s.storage), s.maxCap)
 
    s.cond.Signal() // 唤醒一个消费者
    return nil
}
 
// Get 取出珠宝(消费者用)
func (s *JewelryBoxService) Get() (*domain.Jewel, error) {
    s.mu.Lock()
    defer s.mu.Unlock()
 
    // 等待:箱子非空
    for len(s.storage) == 0 {
        s.logger.Println("质检员等待,珠宝箱为空...")
        s.cond.Wait()
    }
 
    jewel := s.storage[0]
    s.storage = s.storage[1:]
    s.logger.Printf("质检员取出珠宝:%s | 剩余库存:%d", jewel.ID, len(s.storage))
 
    s.cond.Signal() // 唤醒一个生产者
    return jewel, nil
}
 
// BroadcastClose 关闭时唤醒所有协程(防止死锁)
func (s *JewelryBoxService) BroadcastClose() {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.cond.Broadcast()
}
Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Condition Variable  Pattern  条件变量模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/10 20:39
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : worker.go
*/
package worker
 
import (
    "fmt"
    "godesginpattern/conditionvariable/common/logger"
    "godesginpattern/conditionvariable/domain"
    "godesginpattern/conditionvariable/service"
    "sync"
    "time"
)
 
// JewelWorker 工匠(生产者)
type JewelWorker struct {
    id     int
    total  int
    box    *service.JewelryBoxService
    logger *logger.Logger
    wg     *sync.WaitGroup
}
 
func NewJewelWorker(id int, total int, box *service.JewelryBoxService, log *logger.Logger, wg *sync.WaitGroup) *JewelWorker {
    return &JewelWorker{
        id:     id,
        total:  total,
        box:    box,
        logger: log,
        wg:     wg,
    }
}
 
// Start 启动生产
func (w *JewelWorker) Start() {
    defer w.wg.Done()
 
    for i := 1; i <= w.total; i++ {
        jewelID := fmt.Sprintf("DIAMOND-%d-%d", w.id, i)
        jewel := domain.NewJewel(jewelID, "DIAMOND", w.id)
 
        err := w.box.Put(jewel)
        if err != nil {
            w.logger.Printf("工匠[%d]生产失败: %v", w.id, err)
            continue
        }
 
        time.Sleep(1 * time.Second) // 打磨耗时
    }
 
    w.logger.Printf("✅ 工匠[%d]完成全部生产任务", w.id)
}
 
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Condition Variable  Pattern  条件变量模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/10 20:40
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : inspector.go
*/
package worker
 
import (
    "godesginpattern/conditionvariable/common/logger"
    "godesginpattern/conditionvariable/service"
    "sync"
    "time"
)
 
// JewelInspector 质检员(消费者)
type JewelInspector struct {
    id     int
    total  int
    box    *service.JewelryBoxService
    logger *logger.Logger
    wg     *sync.WaitGroup
}
 
func NewJewelInspector(id int, total int, box *service.JewelryBoxService, log *logger.Logger, wg *sync.WaitGroup) *JewelInspector {
    return &JewelInspector{
        id:     id,
        total:  total,
        box:    box,
        logger: log,
        wg:     wg,
    }
}
 
// Start 启动质检
func (i *JewelInspector) Start() {
    defer i.wg.Done()
 
    for n := 0; n < i.total; n++ {
        jewel, err := i.box.Get()
        if err != nil {
            i.logger.Printf("质检员[%d]获取珠宝失败: %v", i.id, err)
            continue
        }
 
        i.logger.Printf("🔍 质检员[%d]完成质检: %s", i.id, jewel.ID)
        time.Sleep(1200 * time.Millisecond)
    }
 
    i.logger.Printf("✅ 质检员[%d]完成全部质检任务", i.id)
}

调用:

Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Condition Variable  Pattern  条件变量模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/5/10 20:44
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : conditionvariableBll.go
*/
package bll
 
import (
    "godesginpattern/conditionvariable/common/logger"
    "godesginpattern/conditionvariable/config"
    "godesginpattern/conditionvariable/service"
    "godesginpattern/conditionvariable/worker"
    "sync"
)
 
func ConditionVariableMain() {
    // 1. 初始化基础组件
    log := logger.NewLogger()
    cfg := config.DefaultConfig()
    log.Println("=== 珠宝生产质检系统启动 ===")
 
    // 2. 初始化核心服务(条件变量)
    boxService := service.NewJewelryBoxService(cfg.BoxCapacity, log)
 
    // 3. 等待组
    var wg sync.WaitGroup
 
    // 4. 启动所有工匠(生产者)
    log.Printf("启动 %d 名工匠,每人生产 %d 件珠宝", cfg.WorkerCount, cfg.ProduceCount)
    wg.Add(cfg.WorkerCount)
    for i := 1; i <= cfg.WorkerCount; i++ {
        w := worker.NewJewelWorker(i, cfg.ProduceCount, boxService, log, &wg)
        go w.Start()
    }
 
    // 5. 启动所有质检员(消费者)
    log.Printf("启动 %d 名质检员,每人质检 %d 件珠宝", cfg.InspectorCount, cfg.CheckCount)
    wg.Add(cfg.InspectorCount)
    for i := 1; i <= cfg.InspectorCount; i++ {
        ins := worker.NewJewelInspector(i, cfg.CheckCount, boxService, log, &wg)
        go ins.Start()
    }
 
    // 6. 等待全部完成
    wg.Wait()
 
    // 7. 优雅关闭(唤醒所有等待协程)
    boxService.BroadcastClose()
 
    log.Println("=== 系统任务全部完成,正常退出 ===")
}

输出:

相关推荐
jimy11 小时前
C语言模拟对象、方法:“函数指针+结构体“复用函数指针指向的函数体
c语言·开发语言
程序员张32 小时前
SpringBoot集成BCrypt密码加密库
java·spring boot·后端
CaffeinePro2 小时前
FastAPI数据库集成SQLAlchemy异步ORM全方案
后端·fastapi
小旭Coding2 小时前
凌晨告警轰炸!Go 服务协程只增不减,内存持续暴涨直至 OOM
后端
半个落月2 小时前
用 LangChain.js 手写一个能读写文件和执行命令的 Mini Cursor
javascript·人工智能·后端
天外天-亮2 小时前
HBuilder X 使用 uview-plus 方式
开发语言·javascript·hbuilder x·uview-plus
木木子222 小时前
[特殊字符] 音乐播放器——状态驱动的多媒体控制
android·开发语言·华为·php·harmonyos
952363 小时前
RabbitMQ-基础操作
java·spring boot·分布式·后端·spring·rabbitmq
六个九十度3 小时前
用python脚本访问被网关隔离的嵌入式设备
开发语言·python
柒和远方3 小时前
从审计日志到可下载证据包:事务型 Outbox、租约 fencing 与保留水位
前端·后端·架构