Как узнать, существует ли еще рутин? - PullRequest
1 голос
/ 21 марта 2019

Есть ли такая же функция, как java Thread.isAlive() для goroutine?

Я пытаюсь порождать некоторые подпрограммы, которые предназначены для долгоживущих потоков, но я боюсь, что подпрограмма может умереть в середине процесса, есть ли проверка, которую я могу сделать в моей главной ветке, чтобы увидеть, жива ли подпрограмма?

Ответы [ 4 ]

6 голосов
/ 21 марта 2019

Лучший способ - не знать, пока он жив, а знать, когда он умирает, чтобы вы могли перезапустить его.

Вы можете сделать это, установив defer с recover на своей программе, которая будет записывать в канал, сигнализирующий о смерти программы.Затем в основной программе вы читаете с этого канала, и всякий раз, когда что-то читается, вы перезапускаете программу.Вы можете определить, какая из подпрограмм оказалась неудачной, вернув структуру, содержащую идентификатор подпрограммы и ошибку.

Пример:

package main

import "fmt"

// number of desired workers
const nWorkers = 10

func main() {
        // make a buffered channel with the space for my 10 workers
        workerChan := make(chan *worker, nWorkers)

        for i := 0; i < nWorkers; i++ {
                i := i
                wk := &worker{id: i}
                go wk.work(workerChan)
        }

        // read the channel, it will block until something is written, then a new
        // goroutine will start
        for wk := range workerChan {
                // log the error
                fmt.Printf("Worker %d stopped with err: %s", wk.id, wk.err)
                // reset err
                wk.err = nil
                // a goroutine has ended, restart it
                go wk.work(workerChan)
        }
}

type worker struct {
        id  int
        err error
}

func (wk *worker) work(workerChan chan<- *worker) (err error) {
        // make my goroutine signal its death, wether it's a panic or a return
        defer func() {
                if r := recover(); r != nil {
                        if err, ok := r.(error); ok {
                                wk.err = err
                        } else {
                                wk.err = fmt.Errorf("Panic happened with %v", r)
                        }
                } else {
                        wk.err = err
                }
                workerChan <- wk
        }()

        // do something
        // ...

        return err
}
3 голосов
/ 21 марта 2019

Есть ли такая функция, как java Thread.isAlive () для goroutine?

Нет.Вы должны изменить свое решение.Горутины не имеют идентичности и не могут быть доступны любым способом.

1 голос
/ 21 марта 2019

Нет,
Вы можете реализовать метод канала / синхронизации самостоятельно, чтобы проверить, жива ли конкретная программа.
Также вы можете получить число Goroutines, используя runtime.NumGoroutine(), например:

package main

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
    fmt.Println(runtime.NumGoroutine()) // 1
    go fun2()
    fmt.Println(runtime.NumGoroutine()) // 2
    go fun3()
    fmt.Println(runtime.NumGoroutine()) // 3
    time.Sleep(120 * time.Millisecond)
    fmt.Println(runtime.NumGoroutine()) // 2
}
func fun3() {
    time.Sleep(100 * time.Millisecond)
}
func fun2() {
    select {}
}

0 голосов
/ 21 марта 2019

Да, goroutine имеет уникальный идентификатор в golang, вы можете найти его в пакете времени выполнения.

Но goroutineID не следует использовать, если только не происходит отладка.

Если вы хотите отслеживать одну goroutine,лучший способ - канал или журнал

...