Erfahren Sie, wie Sie skalierbare Select Channels Go-Parallelprogrammierung in Golang entwerfen

王林
Freigeben: 2023-09-28 16:27:30
Original
1087 Leute haben es durchsucht

了解如何在golang中设计可扩展的Select Channels Go并发式编程

Erfahren Sie, wie Sie skalierbare Select Channels Go-Parallelprogrammierung in Golang entwerfen.

Einführung:

Go-Sprache ist eine effiziente und prägnante Parallelprogrammiersprache, deren Parallelitätsmodell hauptsächlich auf Goroutine und Channel basiert. Durch den intuitiven Kommunikationsmechanismus der leichtgewichtigen Threads und Kanäle von Goroutinen bietet das gleichzeitige Programmiermodell der Go-Sprache eine effiziente Möglichkeit, gleichzeitige Aufgaben zu bearbeiten.

In der Go-Sprache ist es üblich, Kanäle für die Kommunikation zu nutzen. Zusätzlich zur grundlegenden Verwendung von Kanälen können wir die Select-Anweisung auch verwenden, um die Auswahl und Kommunikation mehrerer Kanäle zu verwalten und so eine flexiblere und skalierbarere gleichzeitige Programmierung zu erreichen.

In diesem Artikel wird anhand eines Falls erläutert, wie mithilfe ausgewählter Anweisungen und Kanäle ein skalierbares gleichzeitiges Programm entworfen wird.

Fall:

Wir gehen davon aus, dass es einen Aufgabenverteiler gibt und mehrere Arbeitsthreads Aufgaben vom Aufgabenverteiler zur Verarbeitung erhalten. Der Task-Dispatcher passt die Task-Zuteilungsstrategie basierend auf der Länge der Task-Warteschlange und der Anzahl der Arbeitsthreads dynamisch an.

Zuerst definieren wir eine Aufgabenstruktur. Aufgabe:

type Task struct {
    ID    int
    Value int
}
Nach dem Login kopieren

Als nächstes erstellen wir einen Aufgabenverteiler Dispatcher und implementieren zugehörige Methoden:

type Dispatcher struct {
    workerCount  int
    taskQueue    chan Task
    workerDone   chan struct{}
    workerFinish chan struct{}
}

func NewDispatcher(workerCount int) *Dispatcher {
    return &Dispatcher{
        workerCount:  workerCount,
        taskQueue:    make(chan Task),
        workerDone:   make(chan struct{}, workerCount),
        workerFinish: make(chan struct{}),
    }
}

func (d *Dispatcher) Start() {
    for i := 0; i < d.workerCount; i++ {
        go d.worker()
    }

    go d.adjust()
}

func (d *Dispatcher) worker() {
    for task := range d.taskQueue {
        // 处理任务
        fmt.Printf("Worker[%d] processing task %d
", task.ID, task.Value)
        time.Sleep(1 * time.Second)
        d.workerDone <- struct{}{}
    }
}

func (d *Dispatcher) adjust() {
    for {
        select {
        case <-d.workerFinish:
            d.workerCount--
            if d.workerCount == 0 {
                return
            }
        case <-time.After(5 * time.Second):
            if len(d.taskQueue) > 10 && d.workerCount < 5 {
                d.workerCount++
                go d.worker()
            }
        }
    }
}

func (d *Dispatcher) Dispatch(task Task) {
    d.taskQueue <- task
}

func (d *Dispatcher) Wait() {
    for i := 0; i < d.workerCount; i++ {
        <-d.workerDone
    }
    close(d.taskQueue)
    close(d.workerFinish)
    close(d.workerDone)
}
Nach dem Login kopieren

Im Dispatcher definieren wir 4 Kanäle: taskQueue für den Empfang und die Verteilung von Aufgaben, workerDone wird für die Rückgabe von verwendet Aufgabenabschlusssignale, und workerFinish wird zum Zählen und Anpassen von Arbeitsthreads verwendet.

Start-Methode wird verwendet, um den Worker-Thread und den Aufgabenanpassungs-Thread zu starten, wobei die Worker-Methode die spezifische Implementierung des Worker-Threads ist. Jeder Worker-Thread entnimmt die Aufgabe zur Verarbeitung aus der taskQueue und sendet das Abschlusssignal der Aufgabe an workerDone. Die

adjust-Methode ist die spezifische Implementierung des Aufgabenanpassungsthreads. Es verwendet select, um zwei Kanäle zu überwachen. Wenn workerFinish das Signal empfängt, bedeutet dies, dass ein Worker-Thread die Aufgabe abgeschlossen hat und Personalanpassungen vorgenommen werden müssen. Wenn der time.After-Timer ausgelöst wird, bedeutet dies, dass die Länge der Aufgabenwarteschlange zu lang ist und Arbeitsthreads hinzugefügt werden müssen, um mehr Aufgaben zu verarbeiten. Durch die dynamische Anpassung der Anzahl der Worker-Threads können wir die Systemressourcen voll ausnutzen und dafür sorgen, dass Aufgaben schnell verarbeitet werden.

Die Dispatch-Methode wird verwendet, um Aufgaben an den Task-Dispatcher zu senden. Mit der Wait-Methode wird auf den Abschluss aller Aufgaben gewartet.

Anwendungsbeispiel:

func main() {
    dispatcher := NewDispatcher(3)
    dispatcher.Start()
    
    for i := 0; i < 20; i++ {
        task := Task{
            ID:    i,
            Value: i,
        }
        dispatcher.Dispatch(task)
    }
    
    dispatcher.Wait()
}
Nach dem Login kopieren

In diesem Beispiel erstellen wir einen Dispatcher und starten 3 Worker-Threads. Anschließend haben wir 20 Aufgaben an den Disponenten verteilt. Warten Sie abschließend mit der Wait-Methode auf den Abschluss aller Aufgaben.

Zusammenfassung:

Durch die Verwendung ausgewählter Anweisungen und Kanäle können wir skalierbare gleichzeitige Programme flexibel entwerfen. In diesem Fall zeigen wir, wie Sie mithilfe von Select und Channel einen Task-Dispatcher implementieren, der die Task-Verteilungsstrategie dynamisch anpasst. Mit dieser Methode können wir die Systemressourcen voll ausnutzen und die Aufgaben schnell bearbeiten.

Bei der tatsächlichen gleichzeitigen Programmierung können wir dieses Modell je nach spezifischen Anforderungen und Szenarien weiter ausbauen und optimieren. Ich hoffe, dieser Artikel kann den Lesern helfen, Select und Channels besser zu verstehen und zu verwenden, um skalierbare Go-Parallelprogramme zu entwerfen.

Das obige ist der detaillierte Inhalt vonErfahren Sie, wie Sie skalierbare Select Channels Go-Parallelprogrammierung in Golang entwerfen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage