MST
星途 面试题库

面试题:Go语言通道异常处理之复杂场景协调

假设有多个生产者和多个消费者通过一个共享的缓冲通道进行数据交互。在某个生产者出现资源耗尽的异常情况下,不仅要停止该生产者向通道发送数据,还要确保其他生产者能继续正常工作,同时所有消费者能够正确处理剩余数据并优雅退出。阐述你的设计思路,并给出关键代码片段说明如何进行异常处理和资源协调。
37.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 异常处理:在生产者中捕获资源耗尽异常,一旦捕获到异常,停止向共享缓冲通道发送数据。
  2. 信号传递:通过一个单独的done通道来通知所有消费者,某个生产者出现异常,并且所有生产者都已完成数据发送。
  3. 资源协调:每个生产者完成工作后,向一个producerDone通道发送信号,当所有生产者都发送了信号,且某个生产者出现异常时,关闭done通道,告知消费者可以处理剩余数据并退出。

关键代码片段(以Go语言为例)

package main

import (
    "fmt"
    "sync"
)

func main() {
    const bufferSize = 10
    sharedBuffer := make(chan int, bufferSize)
    producerDone := make(chan struct{})
    done := make(chan struct{})
    var wg sync.WaitGroup

    // 生产者1
    wg.Add(1)
    go func() {
        defer wg.Done()
        for i := 0; i < 10; i++ {
            if i == 5 {
                // 模拟资源耗尽异常
                fmt.Println("Producer 1: Resource exhausted")
                close(producerDone)
                return
            }
            sharedBuffer <- i
        }
        producerDone <- struct{}{}
    }()

    // 生产者2
    wg.Add(1)
    go func() {
        defer wg.Done()
        for i := 10; i < 20; i++ {
            sharedBuffer <- i
        }
        producerDone <- struct{}{}
    }()

    // 消费者
    for i := 0; i < 2; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for {
                select {
                case data, ok := <-sharedBuffer:
                    if!ok {
                        return
                    }
                    fmt.Printf("Consumer received: %d\n", data)
                case <-done:
                    for data := range sharedBuffer {
                        fmt.Printf("Consumer handling remaining: %d\n", data)
                    }
                    return
                }
            }
        }()
    }

    go func() {
        wg.Wait()
        close(producerDone)
    }()

    go func() {
        numProducers := 2
        for i := 0; i < numProducers; i++ {
            <-producerDone
        }
        close(done)
        close(sharedBuffer)
    }()

    select {}
}
  1. 生产者部分:生产者在出现异常(这里模拟为i == 5)时,关闭producerDone通道并返回。正常完成工作时,向producerDone通道发送信号。
  2. 消费者部分:消费者通过select语句监听sharedBufferdone通道。当done通道接收到信号时,处理sharedBuffer中的剩余数据,然后退出。
  3. 资源协调部分:使用wg等待组等待所有生产者完成工作,当所有生产者都完成(包括出现异常的情况),关闭done通道和sharedBuffer通道,使消费者可以正确处理剩余数据并优雅退出。