40分钟学 Go 语言高并发:【实战课程】工作池(Worker Pool)实现

news2025/1/15 10:26:42

工作池(Worker Pool)实战实现

一、知识要点概述

模块核心功能实现难点重要程度
池化设计管理协程生命周期并发安全、资源控制⭐⭐⭐⭐⭐
动态扩缩容根据负载调整池大小平滑扩缩、性能优化⭐⭐⭐⭐
任务分发合理分配任务到worker负载均衡、任务优先级⭐⭐⭐⭐⭐
状态监控监控池的运行状态指标收集、可观测性⭐⭐⭐⭐

让我们先创建一个完整的工作池实现:

package main

import (
    "context"
    "fmt"
    "log"
    "sync"
    "sync/atomic"
    "time"
)

// Task 表示一个任务
type Task struct {
    ID       int
    Priority int           // 任务优先级
    Handler  func() error  // 任务处理函数
    Done     chan error   // 任务完成通知通道
}

// WorkerPool 表示一个工作池
type WorkerPool struct {
    maxWorkers     int32           // 最大worker数量
    minWorkers     int32           // 最小worker数量
    currentWorkers int32           // 当前worker数量
    taskQueue      chan *Task      // 任务队列
    stopCh         chan struct{}   // 停止信号
    workerWg       sync.WaitGroup  // worker等待组
    metrics        *Metrics        // 指标收集
    ctx            context.Context // 上下文
    cancel         context.CancelFunc // 取消函数
}

// Metrics 用于收集指标
type Metrics struct {
    totalTasks      int64         // 总任务数
    completedTasks  int64         // 完成任务数
    failedTasks     int64         // 失败任务数
    processingTasks int32         // 正在处理的任务数
    queueLength     int32         // 队列长度
}

// NewWorkerPool 创建新的工作池
func NewWorkerPool(minWorkers, maxWorkers int, queueSize int) *WorkerPool {
    ctx, cancel := context.WithCancel(context.Background())
    wp := &WorkerPool{
        maxWorkers:     int32(maxWorkers),
        minWorkers:     int32(minWorkers),
        currentWorkers: 0,
        taskQueue:      make(chan *Task, queueSize),
        stopCh:         make(chan struct{}),
        metrics: &Metrics{
            totalTasks:      0,
            completedTasks:  0,
            failedTasks:     0,
            processingTasks: 0,
            queueLength:     0,
        },
        ctx:    ctx,
        cancel: cancel,
    }

    // 启动最小数量的worker
    for i := 0; i < minWorkers; i++ {
        wp.addWorker()
    }

    // 启动自动扩缩容
    go wp.autoScale()
    
    // 启动指标收集
    go wp.collectMetrics()

    return wp
}

// addWorker 添加一个worker
func (wp *WorkerPool) addWorker() {
    atomic.AddInt32(&wp.currentWorkers, 1)
    wp.workerWg.Add(1)

    go func() {
        defer wp.workerWg.Done()
        defer atomic.AddInt32(&wp.currentWorkers, -1)

        for {
            select {
            case task := <-wp.taskQueue:
                if task == nil {
                    return
                }
                
                // 更新指标
                atomic.AddInt32(&wp.metrics.processingTasks, 1)
                
                // 执行任务
                err := task.Handler()
                
                // 更新指标
                atomic.AddInt32(&wp.metrics.processingTasks, -1)
                if err != nil {
                    atomic.AddInt64(&wp.metrics.failedTasks, 1)
                } else {
                    atomic.AddInt64(&wp.metrics.completedTasks, 1)
                }
                
                // 通知任务完成
                if task.Done != nil {
                    task.Done <- err
                    close(task.Done)
                }

            case <-wp.ctx.Done():
                return
            }
        }
    }()
}

// Submit 提交任务
func (wp *WorkerPool) Submit(task *Task) error {
    select {
    case <-wp.ctx.Done():
        return fmt.Errorf("worker pool is stopped")
    case wp.taskQueue <- task:
        atomic.AddInt64(&wp.metrics.totalTasks, 1)
        atomic.AddInt32(&wp.metrics.queueLength, 1)
        return nil
    }
}

// Stop 停止工作池
func (wp *WorkerPool) Stop() {
    wp.cancel()
    close(wp.taskQueue)
    wp.workerWg.Wait()
}

// autoScale 自动扩缩容
func (wp *WorkerPool) autoScale() {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            queueLen := atomic.LoadInt32(&wp.metrics.queueLength)
            currentWorkers := atomic.LoadInt32(&wp.currentWorkers)
            processingTasks := atomic.LoadInt32(&wp.metrics.processingTasks)

            // 根据队列长度和处理中的任务数决定是否需要扩容或缩容
            if queueLen > 0 && currentWorkers < wp.maxWorkers && 
               float64(processingTasks)/float64(currentWorkers) > 0.8 {
                // 扩容
                wp.addWorker()
            } else if queueLen == 0 && currentWorkers > wp.minWorkers && 
                     float64(processingTasks)/float64(currentWorkers) < 0.2 {
                // 缩容
                atomic.AddInt32(&wp.currentWorkers, -1)
            }

        case <-wp.ctx.Done():
            return
        }
    }
}

// collectMetrics 收集指标
func (wp *WorkerPool) collectMetrics() {
    ticker := time.NewTicker(5 * time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            log.Printf("Worker Pool Metrics:\n"+
                "Total Tasks: %d\n"+
                "Completed Tasks: %d\n"+
                "Failed Tasks: %d\n"+
                "Processing Tasks: %d\n"+
                "Queue Length: %d\n"+
                "Current Workers: %d\n",
                atomic.LoadInt64(&wp.metrics.totalTasks),
                atomic.LoadInt64(&wp.metrics.completedTasks),
                atomic.LoadInt64(&wp.metrics.failedTasks),
                atomic.LoadInt32(&wp.metrics.processingTasks),
                atomic.LoadInt32(&wp.metrics.queueLength),
                atomic.LoadInt32(&wp.currentWorkers))

        case <-wp.ctx.Done():
            return
        }
    }
}

func main() {
    // 创建工作池
    pool := NewWorkerPool(2, 10, 100)

    // 模拟提交任务
    for i := 0; i < 20; i++ {
        taskID := i
        task := &Task{
            ID: taskID,
            Handler: func() error {
                // 模拟任务处理
                time.Sleep(time.Second)
                log.Printf("Task %d completed\n", taskID)
                return nil
            },
            Done: make(chan error, 1),
        }

        if err := pool.Submit(task); err != nil {
            log.Printf("Failed to submit task %d: %v\n", taskID, err)
            continue
        }

        // 异步等待任务完成
        go func() {
            if err := <-task.Done; err != nil {
                log.Printf("Task %d failed: %v\n", taskID, err)
            }
        }()
    }

    // 运行一段时间后停止
    time.Sleep(10 * time.Second)
    pool.Stop()
}

让我们看一下工作池的工作流程图:
在这里插入图片描述

二、核心功能详解

1. 池化设计

工作池的核心设计包括以下几个方面:

  1. Worker生命周期管理

    • 创建:通过addWorker方法动态创建
    • 销毁:通过context取消信号控制
    • 状态维护:使用atomic保证并发安全
  2. 任务队列管理

    • 使用带缓冲channel作为任务队列
    • 支持任务优先级
    • 处理队列满/空的情况
  3. 并发安全

    • 使用atomic操作保证计数器安全
    • 使用WaitGroup管理worker数量
    • 使用context控制生命周期

2. 动态扩缩容

扩缩容策略包括:

  1. 扩容条件
if queueLen > 0 && currentWorkers < wp.maxWorkers && 
   float64(processingTasks)/float64(currentWorkers) > 0.8 {
    wp.addWorker()
}
  1. 缩容条件
if queueLen == 0 && currentWorkers > wp.minWorkers && 
   float64(processingTasks)/float64(currentWorkers) < 0.2 {
    atomic.AddInt32(&wp.currentWorkers, -1)
}
  1. 平滑处理
  • 通过定时器控制扩缩容频率
  • 保持最小worker数量
  • 限制最大worker数量

3. 任务分发

任务分发机制包括:

  1. 任务提交
func (wp *WorkerPool) Submit(task *Task) error {
    select {
    case <-wp.ctx.Done():
        return fmt.Errorf("worker pool is stopped")
    case wp.taskQueue <- task:
        atomic.AddInt64(&wp.metrics.totalTasks, 1)
        return nil
    }
}
  1. 任务处理
  • worker从队列获取任务
  • 执行任务处理函数
  • 通知任务完成状态
  1. 负载均衡
  • 任务自动分配给空闲worker
  • 支持任务优先级
  • 避免单个worker过载

4. 状态监控

监控功能包括:

  1. 指标收集
  • 总任务数
  • 完成任务数
  • 失败任务数
  • 处理中任务数
  • 队列长度
  • 当前worker数量
  1. 指标报告
log.Printf("Worker Pool Metrics:\n"+
    "Total Tasks: %d\n"+
    "Completed Tasks: %d\n"+
    "Failed Tasks: %d\n"+
    "Processing Tasks: %d\n"+
    "Queue Length: %d\n"+
    "Current Workers: %d\n",
    ...
  1. 性能监控
  • worker使用率
  • 任务处理延迟
  • 队列等待时间

三、使用建议

  1. 配置选择
  • minWorkers:根据基础负载设置
  • maxWorkers:考虑系统资源上限
  • queueSize:权衡内存使用和任务积压
  1. 错误处理
  • 实现任务重试机制
  • 记录错误日志
  • 设置任务超时
  1. 性能优化
  • 适当的队列大小
  • 合理的扩缩容阈值
  • 避免任务处理时间过长
  1. 监控告警
  • 设置关键指标告警
  • 监控worker数量变化
  • 关注任务处理延迟

四、实战示例

Worker Pool 使用示例的代码:

package main

import (
    "fmt"
    "log"
    "math/rand"
    "time"
)

// 模拟HTTP请求处理任务
type HTTPRequest struct {
    path     string
    duration time.Duration
}

// 模拟HTTP请求处理器
func simulateHTTPHandler(req HTTPRequest) error {
    time.Sleep(req.duration)
    if rand.Float32() < 0.1 { // 10%的失败率
        return fmt.Errorf("failed to process request: %s", req.path)
    }
    return nil
}

func main() {
    // 创建工作池
    pool := NewWorkerPool(5, 20, 1000)

    // 创建一些模拟的HTTP请求
    paths := []string{
        "/api/users",
        "/api/products",
        "/api/orders",
        "/api/payments",
        "/api/inventory",
    }

    // 启动请求生成器
    go func() {
        for i := 0; i < 100; i++ {
            // 随机选择一个路径
            path := paths[rand.Intn(len(paths))]
            
            // 创建请求任务
            req := HTTPRequest{
                path:     path,
                duration: time.Duration(100+rand.Intn(900)) * time.Millisecond,
            }

            // 创建任务
            task := &Task{
                ID:       i,
                Priority: rand.Intn(3), // 0-2的优先级
                Handler: func() error {
                    return simulateHTTPHandler(req)
                },
                Done: make(chan error, 1),
            }

            // 提交任务
            if err := pool.Submit(task); err != nil {
                log.Printf("Failed to submit request %s: %v\n", path, err)
                continue
            }

            // 处理任务结果
            go func(taskID int, taskPath string) {
                if err := <-task.Done; err != nil {
                    log.Printf("Request failed [%d] %s: %v\n", taskID, taskPath, err)
                } else {
                    log.Printf("Request completed [%d] %s\n", taskID, taskPath)
                }
            }(task.ID, req.path)

            // 模拟请求间隔
            time.Sleep(time.Duration(50+rand.Intn(150)) * time.Millisecond)
        }
    }()

    // 运行30秒后停止
    time.Sleep(30 * time.Second)
    pool.Stop()
}

// 扩展WorkerPool增加请求的优先级处理
type PriorityWorkerPool struct {
    *WorkerPool
    highPriorityQueue    chan *Task
    mediumPriorityQueue  chan *Task
    lowPriorityQueue     chan *Task
}

func NewPriorityWorkerPool(minWorkers, maxWorkers, queueSize int) *PriorityWorkerPool {
    return &PriorityWorkerPool{
        WorkerPool:          NewWorkerPool(minWorkers, maxWorkers, queueSize),
        highPriorityQueue:   make(chan *Task, queueSize),
        mediumPriorityQueue: make(chan *Task, queueSize),
        lowPriorityQueue:    make(chan *Task, queueSize),
    }
}

func (pwp *PriorityWorkerPool) Submit(task *Task) error {
    // 根据优先级分发到不同队列
    switch task.Priority {
    case 2: // 高优先级
        select {
        case pwp.highPriorityQueue <- task:
            return nil
        default:
            return fmt.Errorf("high priority queue is full")
        }
    case 1: // 中优先级
        select {
        case pwp.mediumPriorityQueue <- task:
            return nil
        default:
            return fmt.Errorf("medium priority queue is full")
        }
    default: // 低优先级
        select {
        case pwp.lowPriorityQueue <- task:
            return nil
        default:
            return fmt.Errorf("low priority queue is full")
        }
    }
}

// 监控任务处理延迟
type TaskLatencyMonitor struct {
    totalLatency    time.Duration
    processedTasks  int64
    mu             sync.Mutex
}

func (m *TaskLatencyMonitor) recordLatency(start time.Time) {
    m.mu.Lock()
    defer m.mu.Unlock()
    
    m.totalLatency += time.Since(start)
    m.processedTasks++
}

func (m *TaskLatencyMonitor) getAverageLatency() time.Duration {
    m.mu.Lock()
    defer m.mu.Unlock()
    
    if m.processedTasks == 0 {
        return 0
    }
    return m.totalLatency / time.Duration(m.processedTasks)
}

五、进阶功能实现

1. 任务优先级队列

为了处理不同优先级的任务,我们可以实现一个优先级队列:

package main

import (
    "container/heap"
    "sync"
)

// PriorityQueue 实现优先级队列
type PriorityQueue struct {
    sync.RWMutex
    items []*Task
}

func (pq *PriorityQueue) Len() int {
    pq.RLock()
    defer pq.RUnlock()
    return len(pq.items)
}

func (pq *PriorityQueue) Less(i, j int) bool {
    pq.RLock()
    defer pq.RUnlock()
    return pq.items[i].Priority > pq.items[j].Priority
}

func (pq *PriorityQueue) Swap(i, j int) {
    pq.Lock()
    defer pq.Unlock()
    pq.items[i], pq.items[j] = pq.items[j], pq.items[i]
}

func (pq *PriorityQueue) Push(x interface{}) {
    pq.Lock()
    defer pq.Unlock()
    pq.items = append(pq.items, x.(*Task))
}

func (pq *PriorityQueue) Pop() interface{} {
    pq.Lock()
    defer pq.Unlock()
    old := pq.items
    n := len(old)
    item := old[n-1]
    pq.items = old[0 : n-1]
    return item
}

// 添加任务到优先级队列
func (pq *PriorityQueue) Add(task *Task) {
    heap.Push(pq, task)
}

// 获取最高优先级的任务
func (pq *PriorityQueue) Get() *Task {
    if pq.Len() == 0 {
        return nil
    }
    return heap.Pop(pq).(*Task)
}

2. 性能监控与报告

增加一个性能监控模块:

package main

import (
    "fmt"
    "sync/atomic"
    "time"
)

type PerformanceMonitor struct {
    startTime        time.Time
    totalTasks       int64
    completedTasks   int64
    failedTasks      int64
    totalLatency     int64  // 纳秒
    maxLatency       int64  // 纳秒
    minLatency       int64  // 纳秒
}

func NewPerformanceMonitor() *PerformanceMonitor {
    return &PerformanceMonitor{
        startTime:  time.Now(),
        minLatency: int64(^uint64(0) >> 1), // 最大int64值
    }
}

func (pm *PerformanceMonitor) RecordTaskCompletion(latency time.Duration) {
    atomic.AddInt64(&pm.completedTasks, 1)
    latencyNs := int64(latency)
    atomic.AddInt64(&pm.totalLatency, latencyNs)
    
    // 更新最大延迟
    for {
        old := atomic.LoadInt64(&pm.maxLatency)
        if latencyNs <= old || atomic.CompareAndSwapInt64(&pm.maxLatency, old, latencyNs) {
            break
        }
    }
    
    // 更新最小延迟
    for {
        old := atomic.LoadInt64(&pm.minLatency)
        if latencyNs >= old || atomic.CompareAndSwapInt64(&pm.minLatency, old, latencyNs) {
            break
        }
    }
}

func (pm *PerformanceMonitor) RecordTaskFailure() {
    atomic.AddInt64(&pm.failedTasks, 1)
}

func (pm *PerformanceMonitor) GetReport() string {
    completed := atomic.LoadInt64(&pm.completedTasks)
    failed := atomic.LoadInt64(&pm.failedTasks)
    total := completed + failed
    
    if total == 0 {
        return "No tasks processed yet"
    }
    
    avgLatency := time.Duration(atomic.LoadInt64(&pm.totalLatency) / completed)
    maxLatency := time.Duration(atomic.LoadInt64(&pm.maxLatency))
    minLatency := time.Duration(atomic.LoadInt64(&pm.minLatency))
    
    return fmt.Sprintf(
        "Performance Report:\n"+
            "Total Runtime: %v\n"+
            "Total Tasks: %d\n"+
            "Completed Tasks: %d\n"+
            "Failed Tasks: %d\n"+
            "Success Rate: %.2f%%\n"+
            "Average Latency: %v\n"+
            "Max Latency: %v\n"+
            "Min Latency: %v\n"+
            "Throughput: %.2f tasks/second",
        time.Since(pm.startTime),
        total,
        completed,
        failed,
        float64(completed)/float64(total)*100,
        avgLatency,
        maxLatency,
        minLatency,
        float64(total)/time.Since(pm.startTime).Seconds(),
    )
}

3. 重要优化建议

  1. 任务批处理

    • 合并小任务减少开销
    • 实现批量提交接口
    • 优化内存分配
  2. 负载均衡

    • 实现工作窃取算法
    • 动态调整任务分配
    • 避免饥饿问题
  3. 资源管理

    • 实现优雅关闭
    • 处理panic情况
    • 释放资源
  4. 监控告警

    • 设置健康检查
    • 实现自动恢复
    • 记录详细日志

六、总结

工作池的实现需要考虑以下关键点:

  1. 基础架构

    • 合理的接口设计
    • 良好的扩展性
    • 完善的错误处理
  2. 性能优化

    • 减少锁竞争
    • 优化内存使用
    • 提高并发效率
  3. 可靠性

    • 处理边界情况
    • 实现容错机制
    • 保证数据一致性
  4. 可维护性

    • 清晰的代码结构
    • 完善的文档
    • 便于测试和调试

怎么样今天的内容还满意吗?再次感谢观众老爷的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2250846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习3:数据预处理使用Pandas与PyTorch的实践

文章目录 导读一、主题与提纲1.1. 读取数据集1.2. 处理缺失值1.3. 转换为张量格式二、结论本文是经过严格查阅相关权威文献和资料,形成的专业的可靠的内容。全文数据都有据可依,可回溯。特别申明:数据和资料已获得授权。本文内容,不涉及任何偏颇观点,用中立态度客观事实描…

004 MATLAB数值微积分

01 函数的极值点 求解一元函数在区间(x1,x2)中极小值点&#xff1a; xfminbnd(fun,x1,x2)求解初始向量为x0的多元函数极小值点x和对应的极值y [x,y]fminsearch(fun,x0)02 微积分 1.数值微分&#xff1a; 一次微分&#xff1a; diff(x) 若x是一个向量&#xff0c;则返回[x(…

重塑用户体验!快手电商智能巡检平台的实践与探索

导读&#xff1a;随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已经成为推动各行各业创新的重要力量。特别是在用户体验方面&#xff0c;AI 技术的应用不仅解决了许多传统问题&#xff0c;还带来了全新的交互方式和更高的用户满意度。本文将从快手电商B端…

C# 结构体

文章目录 前言一、结构体的定义与基本使用&#xff08;一&#xff09;定义结构体&#xff08;二&#xff09;结构体的使用示例 二、C# 结构的特点&#xff08;一&#xff09;丰富的成员类型&#xff08;二&#xff09;构造函数相关限制与特性&#xff08;三&#xff09;继承方面…

实现Linux平台自定义协议族

一 简介 我们常常在Linux系统中编写socket接收TCP/UDP协议数据&#xff0c;大家有没有想过它怎么实现的&#xff0c;如果我们要实现socket接收自定义的协议数据又该怎么做呢&#xff1f;带着这个疑问&#xff0c;我们一起往下看吧~~ 二 Linux内核函数简介 在Linux系统中要想…

Asp.net core Autofac 案例 注入、AOP 启用接口代理拦截 启用 类代理拦截=== 只会拦截虚方法

资料 core 实现autofac 》》》 安装 如下工具包 安装之后 如出现 这种 》》》编写 AOP类 using Castle.DynamicProxy; using System.Diagnostics;namespace Web01.AOP {/// <summary>/// 日志记录/// </summary>public class LoggingInterceptor : IInterc…

【深度学习】各种卷积—卷积、反卷积、空洞卷积、可分离卷积、分组卷积

在全连接神经网络中&#xff0c;每个神经元都和上一层的所有神经元彼此连接&#xff0c;这会导致网络的参数量非常大&#xff0c;难以实现复杂数据的处理。为了改善这种情况&#xff0c;卷积神经网络应运而生。 一、卷积 在信号处理中&#xff0c;卷积被定义为一个函数经过翻转…

VOLO实战:使用VOLO实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

GPU 服务器厂家:怎样铸就卓越 AI 算力?

文章来源于百家号&#xff1a;GPU服务器厂家 今天咱来聊聊 GPU 服务器厂家那些事儿&#xff0c;而这其中衡量 AI 算力的因素可是关键所在哦。 先讲讲计算速度这一块。咱都知道 AI 那复杂的活儿&#xff0c;像训练超厉害的图像识别模型&#xff0c;得处理海量图像数据&#x…

DroneCAN 最新开发进展,Andrew在Ardupilot开发者大会2024的演讲

本文是Andrew演讲的中文翻译&#xff0c;你可以直接观看视频了解演讲的全部内容&#xff0c;此演讲视频的中文版本已经发布在Ardupilot社区的Blog板块&#xff0c;你可以在 Arudpilot官网&#xff08;https://ardupilot.org) 获取该视频&#xff1a; 你也可以直接通过Bilibili链…

USB Type-C一线通扩展屏:多场景应用,重塑高效办公与极致娱乐体验

在追求高效与便捷的时代&#xff0c;启明智显USB Type-C一线通扩展屏方案正以其独特的优势&#xff0c;成为众多职场人士、娱乐爱好者和游戏玩家的首选。这款扩展屏不仅具备卓越的性能和广泛的兼容性&#xff0c;更能在多个应用场景中发挥出其独特的价值。 USB2.0显卡&#xff…

Android 混淆问题

我的安卓混淆只需要在gradle里面开启就行了。 buildTypes {release {minifyEnabled trueshrinkResources truezipAlignEnabled trueproguardFiles getDefaultProguardFile(proguard-android-optimize.txt), proguard-rules.pro}} minifyEnabled true 这个就是开启方法&#xf…

《硬件架构的艺术》笔记(九):电磁兼容性能设计指南

简介 电子线路易于接收来自其他发射器的辐射信号&#xff0c;这些EMI&#xff08;电磁干扰&#xff09;使得设备内毗邻的元件不能同时工作。这就有必要进行电磁兼容设计以避免系统内有害的电磁干扰。 确保设备不产生多余的辐射&#xff0c;设备也不易受到射频辐射的干扰&…

MR30分布式 IO 模块在冷却水泵系统中的卓越应用

在当今各类工业生产以及大型设施运行的场景中&#xff0c;冷却水泵系统起着至关重要的作用&#xff0c;它犹如保障整个运转体系顺畅运行的 “血液循环系统”&#xff0c;维持着设备适宜的温度环境&#xff0c;确保其稳定、高效地工作。而随着科技的不断发展&#xff0c;明达技术…

【数据分析】布朗运动(维纳过程)

文章目录 一、概述二、数学布朗运动2.1 数学定义2.2 布朗运动的数学模型2.21 标准布朗运动2.22 布朗运动的路径2.23 布朗运动的方程 三、布朗运动在金融学中的应用四、数学构造&#xff08;以傅里叶级数为例&#xff09;4.1 傅里叶级数的基本思想4.2 构造布朗运动 一、概述 布…

3.22【机器学习】决策树作业代码实现

4.1由于决策树只在样本同属于一类或者所有特征值都用完或缺失时生成叶节点&#xff0c;同一节点的样本&#xff0c;在路径上的特征值都相同&#xff0c;而训练集中又没有冲突数据&#xff0c;所以必定存在训练误差为0的决策树 4.2使用最小训练误差会导致过拟合&#xff0c;使得…

数字IC后端实现之PR工具中如何避免出现一倍filler的缝隙?

在数字IC后端实现中&#xff0c;由于有的工艺foundary不提供Filler1&#xff0c;所以PR工具Innovus和ICC2在做标准单元摆放时需要避免出现两个标准单元之间的缝隙间距是Filler1。为了实现这个目的&#xff0c;我们需要给PR工具施加一些特殊的placement constraint&#xff08;典…

群控系统服务端开发模式-应用开发-前端短信配置开发

一、添加视图 在根目录下src文件夹下views文件夹下param文件夹下sms文件夹下&#xff0c;新建index.vue&#xff0c;代码如下 <template><div class"app-container"><div class"filter-container" style"float:left;"><el…

111.有效单词

class Solution {public boolean isValid(String word) {if(word.length()<3){return false;}int countV0,countC0;//分别统计原音和辅音for(int i0;i<word.length();i){if(Character.isLetterOrDigit(word.charAt(i))){if(word.charAt(i)a||word.charAt(i)e||word.charA…

python图像彩色数字化

效果展示&#xff1a; 目录结构&#xff1a; alphabets.py GENERAL {"simple": "%#*-:. ","complex": "$B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_~<>i!lI;:,\"^. " } # Full list could be found here…