Last active
September 9, 2020 07:27
-
-
Save tkm-kj/7888f749c156702e9908e304f6ba8251 to your computer and use it in GitHub Desktop.
golangで並行処理のお勉強
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math/rand" | |
"sync" | |
"time" | |
"github.com/pkg/errors" | |
) | |
func func1(wg *sync.WaitGroup) { | |
defer wg.Done() | |
time.Sleep(time.Second * 15) | |
rand.Seed(time.Now().UnixNano()) | |
if rand.Intn(2) >= 1 { | |
fmt.Println("func1 error!") | |
return | |
} | |
fmt.Println("func1 finish") | |
} | |
func func2(wg *sync.WaitGroup) { | |
defer wg.Done() | |
time.Sleep(time.Second * 10) | |
rand.Seed(time.Now().UnixNano()) | |
if rand.Intn(2) >= 1 { | |
fmt.Println("func2 error!") | |
return | |
} | |
fmt.Println("func2 finish") | |
} | |
// WaitGroupとchannelを組み合わせる方式 | |
// 同時接続の数を絞ることが出来る | |
// 並行処理させたいが、外部の何かに依存している時に有効 | |
func func3(wg *sync.WaitGroup) { | |
defer wg.Done() | |
limit := 10 | |
// 構造体で埋める理由: ディスクリプタ(記述子)の大きさが小さいから(?) | |
// https://dave.cheney.net/2014/03/25/the-empty-struct | |
slots := make(chan struct{}, limit) | |
defer close(slots) | |
var wg2 sync.WaitGroup | |
cnt := 0 | |
for { | |
cnt++ | |
wg2.Add(1) | |
// channel の capacity の性質により、 capacity に空きが無い場合は送信側が処理待ち(ブロック)してくれる | |
slots <- struct{}{} | |
go func(c int) { | |
defer wg2.Done() | |
time.Sleep(time.Second * 1) | |
fmt.Println("index: ", c) | |
// channel に空きが生まれる | |
<-slots | |
}(cnt) | |
if cnt >= 30 { | |
break | |
} | |
} | |
// Wait は繰り返しの外側に書いてあげないと正しく動かないので注意 | |
wg2.Wait() | |
rand.Seed(time.Now().UnixNano()) | |
if rand.Intn(2) >= 1 { | |
fmt.Println("func3 error!") | |
return | |
} | |
fmt.Println("func3 finish") | |
} | |
// WaitGroupのみ | |
// ひたすら同時並行で投げまくりたい && 処理の終わりは確認したい時有効 | |
func func4(wg *sync.WaitGroup) { | |
defer wg.Done() | |
var wg2 sync.WaitGroup | |
for i := 0; i < 60; i++ { | |
wg2.Add(1) | |
go func(index int) { | |
defer wg2.Done() | |
time.Sleep(time.Second * 1) | |
rand.Seed(time.Now().UnixNano()) | |
fmt.Println("func4: ", index) | |
}(i) | |
} | |
wg2.Wait() | |
rand.Seed(time.Now().UnixNano()) | |
if rand.Intn(2) >= 1 { | |
fmt.Println("func4 error!") | |
return | |
} | |
fmt.Println("func4 finish") | |
} | |
func func5(wg *sync.WaitGroup) { | |
defer wg.Done() | |
time.Sleep(time.Second * 5) | |
rand.Seed(time.Now().UnixNano()) | |
if rand.Intn(2) >= 1 { | |
fmt.Println("func5 error!") | |
return | |
} | |
fmt.Println("func5 finish") | |
} | |
func main() { | |
fmt.Println("start!") | |
var wg sync.WaitGroup | |
wg.Add(6) | |
go func1(&wg) | |
go func2(&wg) | |
go func3(&wg) | |
go func4(&wg) | |
go func5(&wg) | |
go func() { | |
defer wg.Done() | |
time.Sleep(time.Second * 3) | |
fmt.Printf("%+v\n", errors.Wrap(errors.New("anonymous function error!"), "")) | |
}() | |
wg.Wait() | |
fmt.Println("finish!") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment