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("=== 系统任务全部完成,正常退出 ===")
}

输出:

相关推荐
Penge6668 分钟前
Go 接口编译期断言
后端
我是一颗柠檬17 分钟前
【MySQL全面教学】MySQL面试高频考点汇总Day15(2026年)
数据库·后端·mysql·面试
星空椰44 分钟前
Python 面向对象高级:继承与类定义详解
开发语言·python
拽着尾巴的鱼儿1 小时前
springboot openfeign 自定义feign 接口重试机制
java·spring boot·后端
白露与泡影1 小时前
2026大厂Java面试题大全!牛客网最新版
java·开发语言
Ceelog1 小时前
久坐党自救指南:屏幕前 8 小时,身体到底在经历什么
前端·后端
凯瑟琳.奥古斯特1 小时前
高阶子查询题目精炼
开发语言·数据库·python·职场和发展·数据库开发
雪度娃娃1 小时前
转向现代C++——在意为改写的函数添加 override
开发语言·c++
XS0301062 小时前
并发编程 六
java·后端
雪宫街道2 小时前
synchronized 锁的范围:对象锁、类锁与代码块锁
java·jvm·后端·面试