0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Goroutine エクササイズ

Last updated at Posted at 2017-06-27

先輩からお題が出されたので、忘れないように記載しておく

お題

Sleep関数を2秒以内に50回実施して、停止した最大、最小、平均ミリ秒数を表示してください

package main

import (
    "math/rand"
    "time"
    "fmt"
)

 func Sleep(i chan int) {
    r := rand.Intn(500) + 100 // 止まるミリ秒数の定義.ランダム数
    time.Sleep(time.Duration(r) * time.Millisecond) // 止まるミリ秒数の定義
    fmt.Printf("I Slept %d millseconds. \n", r)
    i <- r
}

func main() {
    rand.Seed(time.Now().UnixNano())
    // Sleep関数を2秒以内に50回実施して、停止した最大、最小、平均ミリ秒数を表示してください
}

自分の回答

package main

import (
	"math/rand"
	"time"
	"fmt"
	"sync"
	"strconv"
)

func Sleep(i chan int) {
	r := rand.Intn(500) + 100 // 止まるミリ秒数の定義.ランダム数
	time.Sleep(time.Duration(r) * time.Millisecond) // 止まるミリ秒数の定義
	fmt.Printf("I Slept %d millseconds. \n", r)
	i <- r
}

func max(a []int) int {
	max := a[0]
	for _, i := range a {
		if i > max {
			max = i
		}
	}
	return max
}

func min(a []int) int {
	min := a[0]
	for _, i := range a {
		if i < min {
			min = i
		}
	}
	return min
}

func avg(a []int) int {
	len := len(a)
	sum := 0
	for _, i := range a {
		sum += i
	}
	return sum / len
}

func main() {
	rand.Seed(time.Now().UnixNano())
	// Sleep関数を2秒以内に50回実施して、停止した最大、最小、平均ミリ秒数を表示してください

	// チャネルを用意
	ch := make(chan int)
	finished := make(chan int)

	// Sleep関数を50回、並列処理で実行
	wg := &sync.WaitGroup{}
	for i := 0 ; i < 50 ; i++ {
		wg.Add(1)
		go func() {
			Sleep(ch)
			wg.Done()
		}()
	}

	// 全ての並行処理が完了するのを待つ、完了次第、本スレッドに通知
	go func(){
		wg.Wait()
		finished <- 1
	}()

	// 本スレッドで、並列で実行した結果を受け取る
	results := []int{}
	LOOP:
		for {
			select {
			case v := <- ch:
				results = append(results, v)
			case <- finished:
				break LOOP
			}
		}

	// 結果の集計
	fmt.Println("件数:" + strconv.Itoa(len(results)))
	fmt.Println("最大:" + strconv.Itoa(max(results)))
	fmt.Println("最小:" + strconv.Itoa(min(results)))
	fmt.Println("平均:" + strconv.Itoa(avg(results)))
}

実行結果

件数:50
最大:573
最小:108
平均:311

「ここはこうした方が良い」など、ありましたらコメントいただければ幸いです。

別の方法も考えてみた

チャネルに結果を溜め込んで、完了後に取り出して集計する、今回のはこれで十分っぽい。

package main

import (
	"math/rand"
	"time"
	"fmt"
	"sync"
	"strconv"
)

func Sleep(i chan int) {
	r := rand.Intn(500) + 100 // 止まるミリ秒数の定義.ランダム数
	time.Sleep(time.Duration(r) * time.Millisecond) // 止まるミリ秒数の定義
	fmt.Printf("I Slept %d millseconds. \n", r)
	i <- r
}

func max(a []int) int {
	max := a[0]
	for _, i := range a {
		if i > max {
			max = i
		}
	}
	return max
}

func min(a []int) int {
	min := a[0]
	for _, i := range a {
		if i < min {
			min = i
		}
	}
	return min
}

func avg(a []int) int {
	l := len(a)
	sum := 0
	for _, i := range a {
		sum += i
	}
	return sum / l
}

func main() {
	rand.Seed(time.Now().UnixNano())
	// Sleep関数を2秒以内に50回実施して、停止した最大、最小、平均ミリ秒数を表示してください

	// チャネルを用意
	ch := make(chan int, 50)

	// Sleep関数を50回、並列処理で実行
	wg := &sync.WaitGroup{}
	for i := 0 ; i < 50 ; i++ {
		wg.Add(1)
		go func() {
			Sleep(ch)
			wg.Done()
		}()
	}

	// 全ての並行処理が完了するのを待つ
	wg.Wait()
	close(ch)

	// 並列で実行した結果を受け取る
	results := []int{}
	for v := range ch {
		results = append(results, v)
	}

	// 結果の集計
	fmt.Println("件数:" + strconv.Itoa(len(results)))
	fmt.Println("最大:" + strconv.Itoa(max(results)))
	fmt.Println("最小:" + strconv.Itoa(min(results)))
	fmt.Println("平均:" + strconv.Itoa(avg(results)))
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?