Created
November 6, 2015 08:51
-
-
Save timblair/f4cc410769e7a868dfed to your computer and use it in GitHub Desktop.
Quick stabs at these Go concurrency exercises: http://bit.ly/go-concurrency-exercises
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" | |
) | |
type person string | |
func (p *person) doActivity(a string, min int, max int, wg *sync.WaitGroup) { | |
wg.Add(1) | |
fmt.Println(*p, "started", a) | |
go func() { | |
defer wg.Done() | |
t := time.Second * time.Duration(min+rand.Intn(max-min)) | |
time.Sleep(t) | |
fmt.Println(*p, "spent", t.Seconds(), "seconds", a) | |
}() | |
} | |
func (p *person) GetReady(wg *sync.WaitGroup) { | |
p.doActivity("getting ready", 60, 90, wg) | |
} | |
func (p *person) PutOnShoes(wg *sync.WaitGroup) { | |
p.doActivity("putting on shoes", 35, 45, wg) | |
} | |
type alarm struct{} | |
func (a *alarm) Arm() *time.Timer { | |
return time.NewTimer(60 * time.Second) | |
} | |
func init() { | |
rand.Seed(time.Now().UTC().UnixNano()) | |
} | |
func main() { | |
fmt.Println("Let's got for a walk!") | |
var wg sync.WaitGroup | |
bob, alice := person("Bob"), person("Alice") | |
// 1. Bob and Alice get ready | |
bob.GetReady(&wg) | |
alice.GetReady(&wg) | |
wg.Wait() | |
// 2. Once both are ready, arm alarm | |
fmt.Println("Arming alarm") | |
countdown := new(alarm).Arm() | |
fmt.Println("Alarm is counting down") | |
// 3. Bob and Alice put on their shoes | |
bob.PutOnShoes(&wg) | |
alice.PutOnShoes(&wg) | |
wg.Wait() | |
// 4. Leave the house together and close the door | |
fmt.Println("Exiting and locking the door") | |
// 5. Alarm is armed | |
<-countdown.C | |
fmt.Println("Alarm is armed") | |
} |
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" | |
) | |
type diner string | |
func (d *diner) Eat(buffet <-chan string) { | |
for { | |
select { | |
case m, ok := <-buffet: | |
// If the channel is closed, the buffet is empty | |
if !ok { | |
return | |
} | |
fmt.Println(*d, "is enjoying some", m) | |
t := time.Second * time.Duration(1+rand.Intn(6)) | |
time.Sleep(t) | |
} | |
} | |
} | |
func init() { | |
rand.Seed(time.Now().UTC().UnixNano()) | |
} | |
func main() { | |
fmt.Println("Bon appétite!") | |
diners := []diner{"Alice", "Bob", "Charlie", "Dave"} | |
dishes := []string{ | |
"chorizo", | |
"chopitos", | |
"pimientos de padrón", | |
"croquetas", | |
"patatas bravas", | |
} | |
buffet := make(chan string) | |
var wg sync.WaitGroup | |
// Sit all the diners at the table, ready to eat | |
for _, d := range diners { | |
wg.Add(1) | |
go func(d diner) { | |
defer wg.Done() | |
d.Eat(buffet) | |
}(d) | |
} | |
// Cook up 5-10 morsels of each dish | |
morsels := []string{} | |
for _, dish := range dishes { | |
for i := 0; i < 5+rand.Intn(5); i++ { | |
morsels = append(morsels, dish) | |
} | |
} | |
// Add all the morsels to the buffet in a random order | |
go func() { | |
order := rand.Perm(len(morsels)) | |
for _, i := range order { | |
buffet <- morsels[i] | |
} | |
// Close the buffest to signify everything's been eaten | |
close(buffet) | |
}() | |
// Wait for all diners to finish eating | |
wg.Wait() | |
fmt.Println("That was delicious!") | |
} |
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" | |
"time" | |
) | |
type computer struct{} | |
func (c *computer) Use(t int) { | |
fmt.Println("Tourist", t, "is online") | |
d := time.Second * time.Duration(1+rand.Intn(6)) | |
time.Sleep(d) | |
fmt.Println("Tourist", t, "is done, having spent", d, "online") | |
} | |
func init() { | |
rand.Seed(time.Now().UTC().UnixNano()) | |
} | |
func main() { | |
terminals := make(chan *computer, 5) | |
for i := 0; i < cap(terminals); i++ { | |
terminals <- new(computer) | |
} | |
for _, t := range rand.Perm(25) { | |
select { | |
case c := <-terminals: | |
go func(t int) { | |
defer func() { | |
// Add the now-free computer back to the pool | |
terminals <- c | |
}() | |
c.Use(t) | |
}(t) | |
} | |
} | |
fmt.Println("The place is empty, let's close up and go to the beach!") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment