官术网_书友最值得收藏!

Serial task execution with goroutines

We took a list of tasks and wrote a program to execute them in a linear and sequential manner. However, we want to execute the tasks concurrently! Let's start by first introducing goroutines for the split tasks and see how it goes. We will only show the code snippet where the code actually changed here:

/******************************************************************** 
  We start by making Writing Mail & Listening Audio Book concurrent. 
*********************************************************************/ 
// Tasks that will be executed in parts 
 
// Writing Mail 
func writeAMail() { 
    fmt.Println("Wrote 1/3rd of the mail.") 
    go continueWritingMail1()  // Notice the addition of 'go' keyword. 
} 
func continueWritingMail1() { 
    fmt.Println("Wrote 2/3rds of the mail.") 
    go continueWritingMail2()  // Notice the addition of 'go' keyword. 
} 
func continueWritingMail2() { 
    fmt.Println("Done writing the mail.") 
} 
 
// Listening to Audio Book 
func listenToAudioBook() { 
    fmt.Println("Listened to 10 minutes of audio book.") 
    go continueListeningToAudioBook()  // Notice the addition of 'go'   keyword. 
} 
func continueListeningToAudioBook() { 
    fmt.Println("Done listening to audio book.") 
} 

The following is a possible output:

Done making hotel reservation.
Done booking flight tickets.
Done ordering a dress.
Done paying Credit Card bills.
Wrote 1/3rd of the mail.
Listened to 10 minutes of audio book.

Whoops! That's not what we were expecting. The output from the continueWritingMail1, continueWritingMail2, and continueListeningToAudioBook functions is missing; the reason being that we are using goroutines. Since goroutines are not waited upon, the code in the main function continues executing and once the control flow reaches the end of the main function, the program ends. What we would really like to do is to wait in the main function until all the goroutines have finished executing. There are two ways we can do this—using channels or using WaitGroup. Since we have Chapter 3, Channels and Messages, dedicated to channels, let's use WaitGroup in this section.

In order to use WaitGroup, we have to keep the following in mind:

  • Use WaitGroup.Add(int) to keep count of how many goroutines we will be running as part of our logic.
  • Use WaitGroup.Done() to signal that a goroutine is done with its task.
  • Use WaitGroup.Wait() to wait until all goroutines are done.
  • Pass WaitGroup instance to the goroutines so they can call the Done() method.

Based on these points, we should be able to modify the source code to use WaitGroup. The following is the updated code:

package main 
 
import ( 
    "fmt" 
    "sync" 
) 
 
// Simple individual tasks 
func makeHotelReservation(wg *sync.WaitGroup) { 
    fmt.Println("Done making hotel reservation.") 
    wg.Done()
} func bookFlightTickets(wg *sync.WaitGroup) { fmt.Println("Done booking flight tickets.") wg.Done() } func orderADress(wg *sync.WaitGroup) { fmt.Println("Done ordering a dress.") wg.Done() } func payCreditCardBills(wg *sync.WaitGroup) { fmt.Println("Done paying Credit Card bills.") wg.Done() } // Tasks that will be executed in parts // Writing Mail func writeAMail(wg *sync.WaitGroup) { fmt.Println("Wrote 1/3rd of the mail.") go continueWritingMail1(wg) } func continueWritingMail1(wg *sync.WaitGroup) { fmt.Println("Wrote 2/3rds of the mail.") go continueWritingMail2(wg) } func continueWritingMail2(wg *sync.WaitGroup) { fmt.Println("Done writing the mail.") wg.Done() } // Listening to Audio Book func listenToAudioBook(wg *sync.WaitGroup) { fmt.Println("Listened to 10 minutes of audio book.") go continueListeningToAudioBook(wg) } func continueListeningToAudioBook(wg *sync.WaitGroup) { fmt.Println("Done listening to audio book.") wg.Done() } // All the tasks we want to complete in the day. // Note that we do not include the sub tasks here. var listOfTasks = []func(*sync.WaitGroup){ makeHotelReservation, bookFlightTickets, orderADress, payCreditCardBills, writeAMail, listenToAudioBook, } func main() { var waitGroup sync.WaitGroup // Set number of effective goroutines we want to wait upon waitGroup.Add(len(listOfTasks)) for _, task := range listOfTasks{ // Pass reference to WaitGroup instance // Each of the tasks should call on WaitGroup.Done() task(&waitGroup) } // Wait until all goroutines have completed execution. waitGroup.Wait() }

Here is one possible output order; notice how continueWritingMail1 and continueWritingMail2 were executed at the end after listenToAudioBook and continueListeningToAudioBook:

Done making hotel reservation.
Done booking flight tickets.
Done ordering a dress.
Done paying Credit Card bills.
Wrote 1/3rd of the mail.
Listened to 10 minutes of audio book.
Done listening to audio book.
Wrote 2/3rds of the mail.
Done writing the mail.
主站蜘蛛池模板: 青川县| 台东县| 江源县| 治多县| 尚志市| 南郑县| 锦州市| 盐边县| 台东县| 河北省| 临武县| 克什克腾旗| 汝南县| 哈巴河县| 阿拉善左旗| 遵化市| 手机| 宁城县| 福建省| 全州县| 上栗县| 尤溪县| 特克斯县| 田东县| 扶余县| 剑川县| 大洼县| 石河子市| 吉隆县| 上饶市| 图片| 罗江县| 金山区| 西充县| 泗阳县| 麦盖提县| 绥棱县| 兴海县| 桐乡市| 六盘水市| 芜湖县|