go:Condition Variable Pattern

项目结构:

image

 

/*
# 版权所有  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),
	}
}

  

/*
# 版权所有  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,
	}
}

  

/*
# 版权所有  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      : jewel.go
*/
package domain

// Jewel 珠宝领域实体(纯业务)
type Jewel struct {
	ID       string
	Type     string
	WorkerID int
}

// NewJewel 创建珠宝
func NewJewel(id string, typ string, workerID int) *Jewel {
	return &Jewel{
		ID:       id,
		Type:     typ,
		WorkerID: workerID,
	}
}

  

/*
# 版权所有  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()
}

  

/*
# 版权所有  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)
}

  、

调用:

/*
# 版权所有  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("=== 系统任务全部完成,正常退出 ===")
}

  

输出:

image

 

posted @ 2026-05-10 21:02  ®Geovin Du Dream Park™  阅读(14)  评论(0)    收藏  举报