轉載【golang併發】

package main

import (
	"fmt"
	"runtime"
	"time"
)

//定義一個實現Job接口的數據
type Score struct {
	Num int
}

//定義對數據的處理
func (s *Score) Do() {
	fmt.Println("num:", s.Num)
	time.Sleep(500 * time.Millisecond) //模擬執行的耗時任務
}

func main() {
	num := 100 * 100 * 2 //開啓 2萬個線程
	// debug.SetMaxThreads(num + 1000) //設置最大線程數
	// 註冊工作池,傳入任務
	// 參數1 worker併發個數
	p := NewWorkerPool(num)
	p.Run()

	//寫入一千萬條數據
	dataNum := 100 * 100 * 100 * 10
	go func() {
		for i := 1; i <= dataNum; i++ {
			sc := &Score{Num: i}
			p.JobQueue <- sc //數據傳進去會被自動執行Do()方法,具體對數據的處理自己在Do()方法中定義
		}
	}()
	//循環打印輸出當前進程的Goroutine 個數
	for {
		fmt.Println("runtime.NumGoroutine() :", runtime.NumGoroutine())
		time.Sleep(5 * time.Second)
	}

}

// --------------------------- Job ---------------------
type Job interface {
	Do()
}
type JobQueue chan Job

// --------------------------- Worker ---------------------
type Worker struct {
	JobChan JobQueue //每一個worker對象具有JobQueue(隊列)屬性。
}

func NewWorker() Worker {
	return Worker{JobChan: make(chan Job)}
}

//啓動參與程序運行的Go程數量
func (w Worker) Run(wq chan JobQueue) {
	go func() {
		for {
			wq <- w.JobChan //處理任務的Go程隊列數量有限,每運行1個,向隊列中添加1個,隊列剩餘數量少1個 (JobChain入隊列)
			select {
			case job := <-w.JobChan:
				//fmt.Println("xxx2:",w.JobChan)
				job.Do() //執行操作
			}
		}
	}()
}

// --------------------------- WorkerPool ---------------------
type WorkerPool struct { //線程池:
	Workerlen   int           //線程池的大小
	JobQueue    JobQueue      //Job隊列,接收外部的數據
	WorkerQueue chan JobQueue //worker隊列:處理任務的Go程隊列
}

func NewWorkerPool(workerlen int) *WorkerPool {
	return &WorkerPool{
		Workerlen:   workerlen,
		JobQueue:    make(JobQueue),
		WorkerQueue: make(chan JobQueue, workerlen),
	}
}
func (wp *WorkerPool) Run() {
	fmt.Println("初始化worker")
	//初始化worker(多個Go程)
	for i := 0; i < wp.Workerlen; i++ {
		worker := NewWorker()
		worker.Run(wp.WorkerQueue) //開啓每一個Go程
	}
	// 循環獲取可用的worker,往worker中寫job
	go func() {
		for {
			select {
			//將JobQueue中的數據存入WorkerQueue
			case job := <-wp.JobQueue: //線程池中有需要待處理的任務(數據來自於請求的任務) :讀取JobQueue中的內容
				worker := <-wp.WorkerQueue //隊列中有空閒的Go程   :讀取WorkerQueue中的內容,類型爲:JobQueue
				worker <- job              //空閒的Go程執行任務  :整個job入隊列(channel) 類型爲:傳遞的參數(Score結構體)
				//fmt.Println("xxx1:",worker)
				//fmt.Printf("====%T  ;  %T======\n",job,worker,)
			}
		}
	}()
}

  地址:https://blog.csdn.net/weixin_42117918/article/details/107561920

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章