個(gè)人soho要怎么做企業(yè)網(wǎng)站網(wǎng)站優(yōu)化招聘
案例
并發(fā)目錄大小統(tǒng)計(jì)
業(yè)務(wù)邏輯
統(tǒng)計(jì)目錄的文件數(shù)量和大小(或其他信息)。示例輸出:
?// 某個(gè)目錄:2637 files 1149.87 MB
實(shí)現(xiàn)思路
-
給定一個(gè)或多個(gè)目錄,并發(fā)的統(tǒng)計(jì)每個(gè)目錄的size,最后累加到一起。
-
當(dāng)目錄中存在子目錄時(shí),遞歸的統(tǒng)計(jì)。
-
每個(gè)目錄的統(tǒng)計(jì)都由獨(dú)立的Goroutine完成
-
累計(jì)總Size由獨(dú)立的Goroutine完成
-
使用Channel傳遞獲取的文件大小
-
使用WaitGroup調(diào)度
核心代碼
?// 讀取目錄內(nèi)容// os.ReadDirfunc ReadDir(name string) ([]DirEntry, error)entries, err := os.ReadDir(dir)?// 取得文件信息info, err := entry.Info()?//判定是否為目錄entry.IsDir()
編碼實(shí)現(xiàn)
?func WalkDir(dirs ...string) string {if len(dirs) == 0 {dirs = []string{"."}}?filesizeCh := make(chan int64, 1)?wg := &sync.WaitGroup{}for _, dir := range dirs {wg.Add(1)go walkDir(dir, filesizeCh, wg)}?go func(wg *sync.WaitGroup) {wg.Wait()close(filesizeCh)}(wg)?var fileNum, sizeTotal int64for filesize := range filesizeCh {fileNum++sizeTotal += filesize}?return fmt.Sprintf("%d files %.2f MB\n", fileNum, float64(sizeTotal)/1e6)}func walkDir(dir string, fileSizes chan<- int64, wg *sync.WaitGroup) {defer wg.Done()for _, fileinfo := range fileInfos(dir) {if fileinfo.IsDir() {subDir := filepath.Join(dir, fileinfo.Name())wg.Add(1)go walkDir(subDir, fileSizes, wg)} else {fileSizes <- fileinfo.Size()}}}func fileInfos(dir string) []fs.FileInfo {entries, err := os.ReadDir(dir)if err != nil {fmt.Fprintf(os.Stderr, "walkdir: %v\n", err)return []fs.FileInfo{}}infos := make([]fs.FileInfo, 0, len(entries))for _, entry := range entries {info, err := entry.Info()if err != nil {continue}infos = append(infos, info)}return infos}
測(cè)試執(zhí)行
?> go test -run=WalkDir70 files 0.09 MB?PASSok ? ? goConcurrency ? 0.321s
快速排序的并發(fā)編程實(shí)現(xiàn)
典型的單線程快速排序?qū)崿F(xiàn)
?func QuickSortSingle(arr []int) []int {// 確保arr中至少存在2個(gè)或以上元素if arr == nil || len(arr) < 2 {return arr}// 執(zhí)行排序quickSortSingle(arr, 0, len(arr)-1)return arr}?func quickSortSingle(arr []int, l, r int) {// 判定待排序范圍是否合法if l < r {// 獲取參考元素位置索引mid := partition(arr, l, r)// 遞歸排序左邊quickSortSingle(arr, l, mid-1)// 遞歸排序右邊quickSortSingle(arr, mid+1, r)}}?// 大小分區(qū),返回參考元素索引func partition(arr []int, l, r int) int {p := l - 1for i := l; i <= r; i++ {if arr[i] <= arr[r] {p++swap(arr, p, i)}}return p}?// 交換arr中i和j元素func swap(arr []int, i, j int) {t := arr[i]arr[i] = arr[j]arr[j] = t}
并發(fā)編程實(shí)現(xiàn)思路
-
使用獨(dú)立的Goroutine完成arr中某部分的排序
-
WaitGroup 完成等待阻塞同步
編碼實(shí)現(xiàn)
?// QuickSortConcurrency 快速排序調(diào)用函數(shù)func QuickSortConcurrency(arr []int) []int {// 一:校驗(yàn)arr是否滿足排序需要,至少要有2個(gè)元素if arr == nil || len(arr) < 2 {return arr}?// 四:同步的控制wg := &sync.WaitGroup{}// 二:執(zhí)行排序// 初始排序整體[0, len(arr)-1]wg.Add(1)go quickSortConcurrency(arr, 0, len(arr)-1, wg)wg.Wait()?// 三:返回結(jié)果return arr}?// 實(shí)現(xiàn)遞歸快排的核心函數(shù)// 接收arr,和排序區(qū)間的索引位置[l, r]func quickSortConcurrency(arr []int, l, r int, wg *sync.WaitGroup) {// 一:-1wg的計(jì)數(shù)器defer wg.Done()?// 二:判定是否需要排序, l < rif l < r {// 三:大小分區(qū)元素,并獲取參考元素索引mid := partition(arr, l, r)?// 四:并發(fā)對(duì)左部分排序wg.Add(1)go quickSortConcurrency(arr, l, mid-1, wg)?// 五:并發(fā)的對(duì)右部分排序wg.Add(1)go quickSortConcurrency(arr, mid+1, r, wg)}}
partition 和 swap 部分不變。
測(cè)試執(zhí)行
?func TestQuickSortConcurrency(t *testing.T) {randArr := GenerateRandArr(1000)sortArr := QuickSortConcurrency(randArr)fmt.Println(sortArr)}??// 生成大的隨機(jī)數(shù)組func GenerateRandArr(l int) []int {// 生產(chǎn)大量的隨機(jī)數(shù)arr := make([]int, l)rand.Seed(time.Now().UnixMilli())for i := 0; i < l; i++ {arr[i] = int(rand.Int31n(int32(l * 5)))}?return arr}
?> go test -run=QuickSortConcurrency