test goroutine

This commit is contained in:
Bruce 2018-09-07 21:11:24 +08:00
parent f978e42036
commit f7dd9679d3
No known key found for this signature in database
GPG Key ID: C715526B381CAF28
10 changed files with 138 additions and 7 deletions

View File

@ -62,7 +62,7 @@ A curated collection of idiomatic design & application patterns for Go language.
| Pattern | Description | Status |
|:-------:|:----------- |:------:|
| [N-Barrier](/concurrency/barrier.md) | Prevents a process from proceeding until all N processes reach to the barrier | ✘ |
| [Bounded Parallelism](/concurrency/bounded_parallelism.md) | Completes large number of independent tasks with resource limits | ✔ |
| [Bounded Parallelism](/concurrency/bounded/bounded_parallelism.md) | Completes large number of independent tasks with resource limits | ✔ |
| [Broadcast](/concurrency/broadcast.md) | Transfers a message to all recipients simultaneously | ✘ |
| [Coroutines](/concurrency/coroutine.md) | Subroutines that allow suspending and resuming execution at certain locations | ✘ |
| [Generators](/concurrency/generator.md) | Yields a sequence of values one at a time | ✔ |

View File

@ -33,7 +33,7 @@
* [Semaphore](/synchronization/semaphore.md)
* [Concurrency Patterns](/README.md#concurrency-patterns)
* [N-Barrier](/concurrency/barrier.md)
* [Bounded Parallelism](/concurrency/bounded_parallelism.md)
* [Bounded Parallelism](/concurrency/bounded/bounded_parallelism.md)
* [Broadcast](/concurrency/broadcast.md)
* [Coroutines](/concurrency/coroutine.md)
* [Generators](/concurrency/generator.md)

View File

@ -40,11 +40,11 @@ type (
)
type (
eventObserver struct{
eventObserver struct {
id int
}
eventNotifier struct{
eventNotifier struct {
// Using a map with an empty struct allows us to keep the observers
// unique while still keeping memory usage relatively low.
observers map[Observer]struct{}
@ -84,7 +84,7 @@ func main() {
tick := time.NewTicker(time.Second).C
for {
select {
case <- stop:
case <-stop:
return
case t := <-tick:
n.Notify(Event{Data: t.UnixNano()})

View File

@ -1,6 +1,6 @@
# Bounded Parallelism Pattern
[Bounded parallelism](https://blog.golang.org/pipelines#TOC_9.) is similar to [parallelism](parallelism.md), but allows limits to be placed on allocation.
[Bounded parallelism](https://blog.golang.org/pipelines#TOC_9.) is similar to [parallelism](../parallelism.md), but allows limits to be placed on allocation.
# Implementation and Example

View File

@ -0,0 +1,24 @@
package goroutine
import (
"fmt"
"testing"
"time"
)
func TestFiveGopherWithChan(t *testing.T) {
c := make(chan int)
for i := 0; i < 5; i++ {
go sleepyGopherWithChan(i, c)
}
for i := 0; i < 5; i++ {
gopherID := <-c
fmt.Println("gopher ", gopherID, " has finished sleeping")
}
}
func sleepyGopherWithChan(id int, c chan int) {
time.Sleep(2 * time.Second)
fmt.Println("... ", id, " snore ...")
c <- id
}

View File

@ -0,0 +1,25 @@
package goroutine
import (
"fmt"
"testing"
"time"
)
func TestOneGopher(t *testing.T) {
go sleepyGopher(1)
time.Sleep(3 * time.Second)
}
func TestFiveGopher(t *testing.T) {
c := make(chan int)
for i := 0; i < 5; i++ {
go sleepyGopherWithChan(i, c)
}
time.Sleep(3 * time.Second)
}
func sleepyGopher(id int) {
time.Sleep(2 * time.Second)
fmt.Println("... ", id, " snore ...")
}

View File

@ -0,0 +1,32 @@
package goroutine
import (
"fmt"
"sync"
"testing"
"time"
)
func TestWaitGophers(t *testing.T) {
var gophers = []string{"tom", "peter", "john", "brown"}
var waitGroup sync.WaitGroup
waitGroup.Add(len(gophers))
for i := 0; i < len(gophers); i++ {
go func(wg *sync.WaitGroup, name string) {
sleepyGopherSnore(name)
wg.Done()
}(&waitGroup, gophers[i])
}
waitGroup.Wait()
fmt.Println("All done")
}
func sleepyGopherSnore(name string) {
fmt.Println(name, ": ... start snore")
time.Sleep(2 * time.Second)
fmt.Println(name, ": ... snore")
}

View File

@ -0,0 +1,11 @@
package goroutine
import "testing"
// A deadlock happens when a group of goroutines are waiting for each other and none of them is able to proceed.
// The program will get stuck on the channel send operation waiting forever for someone to read the value.
// Go is able to detect situations like this at runtime.
func TestDeadlock(t *testing.T) {
c := make(chan int)
<-c
}

View File

@ -0,0 +1,39 @@
package goroutine
import (
"fmt"
"strings"
"testing"
)
func sourceGopher(downstream chan string) {
for _, v := range []string{"hello world", "a bad apple", "goodbye all"} {
downstream <- v
}
close(downstream)
}
func filterGopher(upstream, downstream chan string) {
for item := range upstream {
fmt.Println("filter ", item)
if !strings.Contains(item, "bad") {
downstream <- item
}
}
}
func printGopher(upstream chan string) {
for item := range upstream {
fmt.Println("print ", item)
}
}
// Pipeline source->filter->print
func TestPipeline(t *testing.T) {
c0 := make(chan string)
c1 := make(chan string)
go sourceGopher(c0)
go filterGopher(c0, c1)
printGopher(c1)
}