我面臨一個問題,即使在論壇上度過了一天之后,我仍然無法完全理解和解決。
所以在這里,我創建了一個回圈遍歷所有檔案夾及其子檔案夾的函式,它有 2 個子函式: - 對于找到的每個檔案,列出檔案名。- 對于找到的每個檔案夾,重新啟動相同的父函式以再次查找子檔案和檔案夾。
為了使其更簡單,該宏以遞回方式列出了樹中的所有檔案。但我的目標是盡可能快地完成,所以每次遇到新檔案夾時我都會運行一個新的 goroutine。
問題:
我的問題是當樹結構太大(檔案夾和子檔案夾中的檔案夾太多......)時,腳本會生成太多執行緒,因此會給我一個錯誤。所以我增加了這個限制,但突然它不再需要 pc:/
所以我的問題是,我怎樣才能制作一個適合我的代碼的作業系統(帶有 poolsize)?不管我怎么看,我都不知道怎么說,例如,生成新的 goroutine 達到一定的限制,清空緩沖區的時間。
源代碼:
https ://github.com/LaM0uette/FilesDIR/tree/V0.5
主要的:
package main
import (
"FilesDIR/globals"
"FilesDIR/task"
"fmt"
"log"
"runtime/debug"
"sync"
"time"
)
func main() {
timeStart := time.Now()
debug.SetMaxThreads(5 * 1000)
var wg sync.WaitGroup
// task.DrawStart()
/*
err := task.LoopDir(globals.SrcPath)
if err != nil {
log.Print(err.Error())
}
*/
err := task.LoopDirsFiles(globals.SrcPath, &wg) // globals.SrcPath = My path with ~2000000 files ( this is a serveur of my entreprise)
if err != nil {
log.Print(err.Error())
}
wg.Wait()
fmt.Println("FINI: Nb Fichiers: ", task.Id)
timeEnd := time.Since(timeStart)
fmt.Println(timeEnd)
}
任務:
package task
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"sync"
"time"
)
var Id = 0
// LoopDir TODO: Code à supprimer / Code to delete
func LoopDir(path string) error {
var wg sync.WaitGroup
countDir := 0
err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
wg.Add(1)
countDir
go func() {
err := loopFiles(path, &wg)
if err != nil {
log.Println(err.Error())
}
}()
}
return nil
})
if err != nil {
return err
}
wg.Wait()
fmt.Println("Finished", countDir, Id)
return nil
}
// loopFiles TODO: Code à supprimer / Code to delete
func loopFiles(path string, wg *sync.WaitGroup) error {
files, err := ioutil.ReadDir(path)
if err != nil {
wg.Done()
return err
}
for _, file := range files {
if !file.IsDir() {
go fmt.Println(file.Name())
Id
}
}
wg.Done()
return nil
}
func LoopDirsFiles(path string, wg *sync.WaitGroup) error {
wg.Add(1)
defer wg.Done()
files, err := ioutil.ReadDir(path)
if err != nil {
return err
}
for _, file := range files {
if !file.IsDir() && !strings.Contains(file.Name(), "~") {
fmt.Println(file.Name(), Id)
Id
} else if file.IsDir() {
go func() {
err = LoopDirsFiles(filepath.Join(path, file.Name()), wg)
if err != nil {
log.Print(err)
}
}()
time.Sleep(20 * time.Millisecond)
}
}
return nil
}
uj5u.com熱心網友回復:
如果您不想使用任何外部包,您可以創建一個單獨的作業程式來處理檔案,然后啟動任意數量的作業程式。之后,在主執行緒中遞回地進入樹,并將作業發送給作業人員。如果任何工人“有時間”,它將從作業通道中選擇以下作業并進行處理。
var (
wg *sync.WaitGroup
jobs chan string = make(chan string)
)
func loopFilesWorker() error {
for path := range jobs {
files, err := ioutil.ReadDir(path)
if err != nil {
wg.Done()
return err
}
for _, file := range files {
if !file.IsDir() {
fmt.Println(file.Name())
}
}
wg.Done()
}
return nil
}
func LoopDirsFiles(path string) error {
files, err := ioutil.ReadDir(path)
if err != nil {
return err
}
//Add this path as a job to the workers
//You must call it in a go routine, since if every worker is busy, then you have to wait for the channel to be free.
go func() {
wg.Add(1)
jobs <- path
}()
for _, file := range files {
if file.IsDir() {
//Recursively go further in the tree
LoopDirsFiles(filepath.Join(path, file.Name()))
}
}
return nil
}
func main() {
//Start as many workers you want, now 10 workers
for w := 1; w <= 10; w {
go loopFilesWorker()
}
//Start the recursion
LoopDirsFiles(globals.SrcPath)
wg.Wait()
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/456730.html
上一篇:從textarea中查找分隔符
下一篇:按選擇計數(*)欄位排序非常慢
