2016-09-22 2 views
3

У меня есть некоторые goroutine логики, как это:Как закрыть goroutine, который управляет логикой потока?

go func() { 
    do_things_0() 
    do_things_1() 
    do_things_2() 
    do_things_3() 
    ... 
    ... 
}() 

Когда служба получает запрос, он будет создавать такую ​​goroutine. И goroutine, возможно, потребляет память и требует более 30 минут.

Иногда служба может заметить недостаток памяти, и ей необходимо прекратить работу некоторых горутов.

Мои вопросы:

  1. Как я могу прекратить goroutine в приведенном выше примере?
  2. Есть ли способ узнать используемую память каждого горутина?

Update

  1. Я читал другие SO ответы, которые goroutine не могут быть убиты за пределами
  2. Я полагаю, что послать сигнал в канал, обрабатываемого goroutine, чтобы сделать goroutine бросить это подходит только для for loop based logics.
  3. Я искал некоторые рекомендации по закрытию goroutine для flow based logics.
+1

1) Вы не можете (см. Ниже). 2) Нет никакого способа сделать это. Чтобы «остановить» goroutine, вы должны изобрести механизм, чтобы убить его снаружи (например, закрыв канал, обработанный для goroutine). – Volker

+2

Вы не можете остановить/убить горутин. См. Соответствующий вопрос: [отменить операцию блокировки в Go] (http://stackoverflow.com/questions/28240133/cancel-a-blocking-operation-in-go) – icza

+0

@Volker Я знаю, что я могу закрыть канал, чтобы сделать goroutine закрывается, но я полагаю, что это полезно только для goroutine, который запускает цикл, подобный логике. Я не нашел удобного способа закрыть горутин для такого гортана с потоком. – pengdu

ответ

1

Вы должны быть в состоянии приспособить это легко к for цикла, если вы range над списком функций, которые ваши шаги:

package main 

import (
    "fmt" 
    "time" 
) 

func a() { fmt.Printf("a") } 
func b() { fmt.Printf("b") } 
func c() { fmt.Printf("c") } 
func d() { fmt.Printf("d") } 
func e() { fmt.Printf("e") } 

func f(quit <-chan struct{}) { 
    for i := 0; i < 10000; i++ { 
     for _, fn := range []func(){a, b, c, d, e} { 
      select { 
      case _, _ = <-quit: 
       fmt.Println("quit f") 
       return 
      default: 
       fn() 
       time.Sleep(1 * time.Millisecond) 
      } 
     } 
    } 
} 

func main() { 
    quit := make(chan struct{}) 
    fmt.Println("go f") 
    go f(quit) 
    fmt.Println("sleep") 
    time.Sleep(100 * time.Millisecond) 
    fmt.Println("\nquit") 
    close(quit) 
    time.Sleep(10 * time.Millisecond) 
    fmt.Println("exit") 
} 

Попробуйте на playground.

Внешняя петля - это просто, чтобы повторить шаги достаточно долго, чтобы мы могли наблюдать за командой quit.

+0

хорошая идея! благодаря! – pengdu

Смежные вопросы