自学内容网 自学内容网

Golang_交替打印ABC\奇偶数\1-10\字母(并发编程)

一、常见题目

1.1 三个协程交替打印ABC

建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。

package main
import(
"fmt"
"sync"
)
var wg sync.WaitGroup
var ch1, ch2, ch3 = make(chan int), make(chan int), make(chan int)
func print_A(){
defer wg.Done()
for i := 0; i < 10; i++ {
<- ch1
fmt.Print("A")
ch2 <- 1
}
<- ch1
}

func print_B(){
defer wg.Done()
for i := 0; i < 10; i++{
// a.Done()
// fmt.Print("B")
// b.Add(1)
<- ch2
fmt.Print("B")
ch3 <- 1
}
}

func print_C(){
// print_C运行结束wg再-1
defer wg.Done()
for i := 0; i < 10; i++{
<- ch3
fmt.Print("C")
ch1 <- 1
}
}
// 建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,
// 但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。

func main(){
// wg确保main函数在所有协程运行完毕再退出
wg.Add(3)
go print_A()
go print_B()
go print_C()
// 确保所有 goroutine 都已经启动并准备好接收信号,然后再发送第一个信号。这样可以避免在开始时出现竞争条件或死锁。
ch1 <- 1
wg.Wait()
fmt.Println("    Done")
}

1.2 并发访问多个URL,存储状态信息

package main

import (
    "fmt"
    "net/http"
    "sync"
)

// fetchURL 发送 HTTP GET 请求并返回响应状态码,如果请求出错则返回错误信息。
func fetchURL(url string) (string, error) {
    resp, err := http.Get(url)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    // fmt.Printf("Fetched %s with status: %s\n", url, resp.Status) // 调试输出

    return resp.Status, nil
}

func main() {
    urls := []string{
        "https://www.zijie.com",
        "https://www.baidu.com",
        "https://www.alibaba.com",
        // 添加更多的 URL...
    }

    results := make(chan string)
    var wg sync.WaitGroup

    // 启动 goroutine 发送 HTTP 请求
    for _, url := range urls {
// _:0,1,2
        wg.Add(1) // 每个 goroutine 开始前增加 WaitGroup 的计数器
        go func(url string) {
            defer wg.Done()

            data, err := fetchURL(url)
            if err != nil {
                fmt.Println("Error fetching", url, ":", err)
                return
            }
// data写给管道
            results <- data
// url作为参数
        }(url)
    }

    // 启动一个 goroutine 等待所有任务完成后关闭通道
    go func() {
        wg.Wait()    // 等待所有 goroutine 完成
        close(results) // 当所有请求处理完毕后关闭通道,告知 range 循环停止
    }()

    // 从通道中读取并处理每个 URL 请求的响应状态码
    for result := range results {
        // 这里可以将获取到的数据进行处理,例如打印或保存到文件中
        fmt.Println(result)
    }
}

1.3 生成随机数并且计算各个位数之和再打印

// 使用 goroutine 和 channel 实现一个计算int64随机数各位数和的程序,例如生成随机数61345,计算其每个位数上的数字之和为19。

// 1. 开启一个 goroutine 循环生成int64类型的随机数,发送到`jobChan`
// 2. 开启24个 goroutine 从`jobChan`中取出随机数计算各位数的和,将结果发送到`resultChan`
// 3. 主 goroutine 从`resultChan`取出结果并打印到终端输出

package main

import (
"fmt"
"math/rand"
"sync"
)

// ch1, ch2:= make(chan int),make(chan int)

func cal_num(n int64) int{
sum := 0
for n != 0{
sum += int(n%10)
n /= 10
}
// fmt.Println(n, "数字之和", sum)
return sum
}

func main(){
jobChan,resultChan:= make(chan int64),make(chan int)
var wg sync.WaitGroup
// 开启一个 goroutine 循环生成int64类型的随机数,发送到`jobChan`
go func ()  {
for{
randomNumber := rand.Int63()
jobChan <-randomNumber
}

}()
// 开启24个 goroutine 从`jobChan`中取出随机数计算各位数的和,将结果发送到`resultChan`
for i :=0;i<24;i++{
wg.Add(1)
go func ()  {
defer wg.Done()
for{
select{
case num:= <- jobChan:
sum := cal_num(num)
// fmt.Println(num, "数字之和", sum)
resultChan <- sum
}
}
}()
}
go func(){
for c:=range resultChan{
fmt.Println(c)
}
}()
wg.Wait()  // 等待所有 goroutine 完成
}


原文地址:https://blog.csdn.net/weixin_45440484/article/details/140593504

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!