mirror of
https://github.com/crazybber/awesome-patterns.git
synced 2024-11-24 13:36:03 +03:00
test goroutine
This commit is contained in:
parent
f978e42036
commit
f7dd9679d3
@ -62,7 +62,7 @@ A curated collection of idiomatic design & application patterns for Go language.
|
|||||||
| Pattern | Description | Status |
|
| Pattern | Description | Status |
|
||||||
|:-------:|:----------- |:------:|
|
|:-------:|:----------- |:------:|
|
||||||
| [N-Barrier](/concurrency/barrier.md) | Prevents a process from proceeding until all N processes reach to the barrier | ✘ |
|
| [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 | ✘ |
|
| [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 | ✘ |
|
| [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 | ✔ |
|
| [Generators](/concurrency/generator.md) | Yields a sequence of values one at a time | ✔ |
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
* [Semaphore](/synchronization/semaphore.md)
|
* [Semaphore](/synchronization/semaphore.md)
|
||||||
* [Concurrency Patterns](/README.md#concurrency-patterns)
|
* [Concurrency Patterns](/README.md#concurrency-patterns)
|
||||||
* [N-Barrier](/concurrency/barrier.md)
|
* [N-Barrier](/concurrency/barrier.md)
|
||||||
* [Bounded Parallelism](/concurrency/bounded_parallelism.md)
|
* [Bounded Parallelism](/concurrency/bounded/bounded_parallelism.md)
|
||||||
* [Broadcast](/concurrency/broadcast.md)
|
* [Broadcast](/concurrency/broadcast.md)
|
||||||
* [Coroutines](/concurrency/coroutine.md)
|
* [Coroutines](/concurrency/coroutine.md)
|
||||||
* [Generators](/concurrency/generator.md)
|
* [Generators](/concurrency/generator.md)
|
||||||
|
@ -40,11 +40,11 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
eventObserver struct{
|
eventObserver struct {
|
||||||
id int
|
id int
|
||||||
}
|
}
|
||||||
|
|
||||||
eventNotifier struct{
|
eventNotifier struct {
|
||||||
// Using a map with an empty struct allows us to keep the observers
|
// Using a map with an empty struct allows us to keep the observers
|
||||||
// unique while still keeping memory usage relatively low.
|
// unique while still keeping memory usage relatively low.
|
||||||
observers map[Observer]struct{}
|
observers map[Observer]struct{}
|
||||||
@ -84,10 +84,10 @@ func main() {
|
|||||||
tick := time.NewTicker(time.Second).C
|
tick := time.NewTicker(time.Second).C
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <- stop:
|
case <-stop:
|
||||||
return
|
return
|
||||||
case t := <-tick:
|
case t := <-tick:
|
||||||
n.Notify(Event{Data: t.UnixNano()})
|
n.Notify(Event{Data: t.UnixNano()})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Bounded Parallelism Pattern
|
# 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
|
# Implementation and Example
|
||||||
|
|
24
playground/goroutine/basic_chan_test.go
Normal file
24
playground/goroutine/basic_chan_test.go
Normal 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
|
||||||
|
}
|
25
playground/goroutine/basic_test.go
Normal file
25
playground/goroutine/basic_test.go
Normal 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 ...")
|
||||||
|
}
|
32
playground/goroutine/basic_waitgroup_test.go
Normal file
32
playground/goroutine/basic_waitgroup_test.go
Normal 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")
|
||||||
|
}
|
11
playground/goroutine/deadlock_test.go
Normal file
11
playground/goroutine/deadlock_test.go
Normal 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
|
||||||
|
}
|
39
playground/goroutine/pipeline_test.go
Normal file
39
playground/goroutine/pipeline_test.go
Normal 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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user