运行线程一段时间 - 在被杀之前

时间:2016-10-02 01:21:59

标签: go

如何运行10个线程,每个30秒,然后返回程序执行?例如,我想要

  1. 要生成10个线程并运行30秒。
  2. 然后所有线程都被杀死了
  3. 然后second()运行(即在所有线程完成执行后)
  4. 到目前为止,我有以下情况,当我这样做时,线程(显然)继续执行,30秒后CPU使用率保持在100%:

    func main(){
        for i := 0; i < 10; i++{
            go thread()
        }
        time.Sleep(30 * time.Second)
        second()
    }
    
    func thread() {
        for {
            // Do stuff
        }
    }
    

2 个答案:

答案 0 :(得分:1)

使用等待组和&#34;完成&#34;在调用second之前取消正在运行的例程并同步其出口的频道。关于这个主题的一些非常酷的东西可以在这里阅读https://blog.golang.org/pipelines

package main

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

func main() {
    //create a "done" channel that will be used to signal to all go routines running thread to quit
    done := make(chan interface{})

    //create a wait group to sync all go routines before continuing program execution
    wg := new(sync.WaitGroup)

    for i := 0; i < 10; i++ {
        //increment waitgroup
        wg.Add(1)
        go thread(done, wg)
    }
    //zzzz...
    time.Sleep(30 * time.Second)
    //close the done channel
    close(done)
    //wait for all go routines to quit
    wg.Wait()
    //move on
    second()
}

func thread(done chan interface{}, wg *sync.WaitGroup) {
    defer wg.Done()
    working := true
    for working {
        //use a select statement to do work until done channel is closed
        select {
        case <-done:
            //end the loop
            working = false
        default:
            fmt.Println("doing work...")
        }
    }
}

func second() {
    fmt.Println("program complete")
}

答案 1 :(得分:1)

您可以使用Golang上下文。这是我学习它时的一些代码。

package main

import (
    "fmt"
    "log"
    "time"

    "golang.org/x/net/context"
)

func main() {
    someHandler()
}

func someHandler() {
    //Create a new context with a timeout duration of six seconds. You also get a cancel function you can call early. 
    //You can also have context end at a certain time, instead of a timeout
    ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(6))

    for i := 0; i < 5; i++ {
        go doStuff(ctx, i)
    }

    select {
    case <- ctx.Done():
        log.Println("Got a cancel request")
        return
    case <-time.After(time.Second * time.Duration(5)):
        //Here I'm actually ending it earlier than the timeout with cancel().
        log.Println("Timed out")
        cancel()
    }

}

func doStuff(ctx context.Context, num int) {
    for {
        select {
        case <-ctx.Done():
            fmt.Println("Done working")
            return
        default:
            fmt.Println("go", num, "working")
        }
        time.Sleep(time.Second)
    }
}

输出:

$ go run app.go 
go 0 working
go 4 working
go 2 working
go 3 working
go 1 working
go 1 working
go 0 working
go 4 working
go 3 working
go 2 working
go 0 working
go 4 working
go 2 working
go 1 working
go 3 working
go 4 working
go 3 working
go 0 working
go 2 working
go 1 working
go 3 working
go 4 working
go 1 working
go 0 working
go 2 working
2016/10/01 23:25:23 Timed out