Skip to content
鼓励作者:欢迎打赏犒劳

线程阻塞的几种方法

1. 使用信号量 (Signal) 监听 (Go语言中最常见)

这是 Go 程序中等待程序结束的标准做法。

go
package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	ticker := time.NewTicker(3 * time.Second)
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, os.Interrupt, syscall.SIGTERM)

	go func() {
		for t := range ticker.C {
			fmt.Printf("now: %v\n", t)
		}
	}()

	<-stop // 等待中断信号
	fmt.Println("\n程序即将退出")
	ticker.Stop()
}

优点:可以优雅地处理 Ctrl+C (SIGINT) 或系统终止信号 (SIGTERM)。


2. 使用 sync.WaitGroup

当你有多个 goroutine 在运行时,可以用 WaitGroup 等待它们完成。

go
package main

import (
    "fmt"
    "sync"
    "time"
)

func worker(wg *sync.WaitGroup) {
    defer wg.Done()
    time.Sleep(2 * time.Second)
    fmt.Println("工作完成")
}

func main() {
    var wg sync.WaitGroup

    wg.Add(2)
    go worker(&wg)
    go worker(&wg)

    // 等待所有 goroutine 完成
    wg.Wait()
    fmt.Println("所有任务完成,主线程退出")
}

3. 使用 time.Sleep() (仅用于测试)

适用于简单的测试场景,不推荐用于生产环境。

go
package main

import "time"

func main() {
    go func() {
        // 模拟后台任务
        for {
            // do something
            time.Sleep(1 * time.Second)
        }
    }()

    // 让主线程休眠足够长时间
    time.Sleep(1000 * time.Hour)
}

4. 使用 chan struct{} 阻塞

创建一个无缓冲通道并永远阻塞在接收操作上。

go
package main

func main() {
    done := make(chan struct{})

    go func() {
        // 做一些事情...
        // 当需要退出时,可以发送信号:done <- struct{}{}
    }()

    // 主线程阻塞在这里
    <-done
}

5. select {}

永久阻塞,不消耗资源,最佳实践

go
package main

import (
	"fmt"
	"time"
)

func main() {
	ticker := time.NewTicker(3 * time.Second)

	go func() {
		//ticker.C就是当前执行的时间
		for t := range ticker.C {
			fmt.Printf("now: %v\n", t)
		}
	}()

	select {}
}

如有转载或 CV 的请标注本站原文地址