From 267849f86572771f177678e03b5dc80a862c45cd Mon Sep 17 00:00:00 2001 From: Kelu Diao Date: Sat, 21 Nov 2015 02:06:32 -0500 Subject: [PATCH] Multi-threading --- README.md | 4 ++++ script.go | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b5a8aeb..ec0ee49 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@ Gotube is a YouTube downloader using go language. go language is a new light-weight language developed by Google, it provides not only many powerful libraries, but also a simple multi-threading syntax. +This tool is an easy way to download any non-age-restricted videos in YouTube. +You can also perform batch downloading by keywords via search function. +Gotube will generate a number of go-routines (no more than the number of your CPU cores) to download multiple videos simultaneously. + ##Installation - Install go from [https://golang.org/](https://golang.org/) - Set up go environment as in [https://golang.org/doc/install](https://golang.org/doc/install) diff --git a/script.go b/script.go index 01f952e..fa0a041 100644 --- a/script.go +++ b/script.go @@ -5,6 +5,8 @@ import ( "fmt" . "github.com/KeluDiao/gotube/api" "log" + "runtime" + "sync" ) func main() { @@ -77,25 +79,42 @@ func main() { if *isRetList { fmt.Printf("The top %v results for key words \"%v\" are:\n\n", *k, *search) } + //Waiting group is used to prevent main thread ending before child threads end + wg := new(sync.WaitGroup) + wg.Add(len(ids)) + //Channel is used to control the maximum threads + end := make(chan bool, MaxParallelism()) for _, vid := range ids { vl, err = GetVideoListFromId(vid) if err != nil { log.Fatal(err) } - Exec(vl, *isDownload, *isRetList, *rep, *quality, *extension) + go Exec(vl, *isDownload, *isRetList, *rep, *quality, *extension, wg, end) + end <- true } + wg.Wait() return } if err != nil { log.Fatal(err) } - Exec(vl, *isDownload, *isRetList, *rep, *quality, *extension) + //dummy variables + wg := new(sync.WaitGroup) + wg.Add(1) + var end chan bool + Exec(vl, *isDownload, *isRetList, *rep, *quality, *extension, wg, end) } /* * Choose either downloading or retrieving video list */ -func Exec(vl VideoList, isDownload, isRetList bool, rep, quality, extension string) { +func Exec(vl VideoList, isDownload, isRetList bool, rep, quality, extension string, wg *sync.WaitGroup, end chan bool) { + //Set up synchronization function + defer func() { + <- end + wg.Done() + } + if isDownload { fmt.Printf("Downloading %v...\n", vl.Title) err := vl.Download(rep, quality, extension) @@ -110,4 +129,16 @@ func Exec(vl VideoList, isDownload, isRetList bool, rep, quality, extension stri } fmt.Println(vl) } +} + +/* +* Find out the maximum go routines allowed +*/ +func MaxParallelism() int { + maxProcs := runtime.GOMAXPROCS(0) + numCPU := runtime.NumCPU() + if maxProcs < numCPU { + return maxProcs + } + return numCPU } \ No newline at end of file