多线程下载,文件数量未知

foreveriuu · · 1725 次点击
stevewang
耶和华是我的牧者,我必不至缺乏。
按照你的需求,其实是构造一个闭环系统。 因此重要的就是考虑什么时候结束这个闭环。 ``` package main import ( "fmt" "sync" ) // URLInfo 保留构造下载链接的信息 type URLInfo struct { url string page int } func download(info URLInfo) bool { if info.page < 10 { fmt.Printf("%s%03d.dat downloaded \n", info.url, info.page) } else { fmt.Printf("%s%03d.dat download fail \n", info.url, info.page) } return info.page < 10 } func main() { in := make(chan URLInfo, 1) out := make(chan URLInfo, 1) var wg sync.WaitGroup // 分配3个goroutines来下载文件 for i := 0; i < 3; i++ { go func() { for url := range in { if download(url) { // 下载后续三个文件 wg.Add(3) go func(url URLInfo) { for id := 1; id <= 3; id++ { out <- URLInfo{ url: url.url, page: url.page + id, } } }(url) } wg.Done() } }() } // 初始化下载. wg.Add(1) go func() { for _, uri := range []URLInfo{{"AAA", 1}, {"BBB", 1}, {"CCC", 1}} { wg.Add(1) out <- uri } wg.Done() }() // 分发下载任务,过滤重复的文件 go func() { urls := make(map[URLInfo]struct{}) for uri := range out { if _, ok := urls[uri]; ok { wg.Done() } else { urls[uri] = struct{}{} in <- uri } } }() wg.Wait() // 这里所有文件都已经下载完成。 } ```
#11
更多评论
stevewang
耶和华是我的牧者,我必不至缺乏。
用channel配合生产者/消费者模式,就可以控制下载的gorountine数目。 大致流程如下: ``` const ( ThreadCount = 3 ) func main() { ch := make(chan string, ThreadCount) var wg sync.WaitGroup for i := 0; i < ThreadCount; i++ { wg.Add(1) go func() { for url := range ch { download(url) } wg.Done() }() } urls := []string{ "http://www.host.com/AAA001.dat", "http://www.host.com/AAA002.dat", //... } // 分派下载任务 for _, url := range urls { ch <- url } close(ch) wg.Wait() } ```
#1
多谢解答。但是下载数量未知如何解决呢?比如AAA是到了AAA247.dat,但是预先不知道数量,只有尝试AAA247.dat下载失败才知道需要结束,其它BBB、CCC也是如此。
#2