Ausführliche Erklärung des gqueue | Contrast-Kanals von goFrame

Schaffen Sie weiter, beschleunigen Sie das Wachstum! Dies ist der sechste Tag meiner Teilnahme an der „Nuggets Daily New Plan · June Update Challenge“, klicken Sie hier, um die Details der Veranstaltung anzuzeigen

Kanal

Lassen Sie uns zunächst die Rolle des Kanals klären: Er wird für die Kommunikation zwischen go-Coroutinen verwendet.

Das größte Merkmal der Go-Sprache ist die Unterstützung für hohe Parallelität: Goroutinen und Kanäle sind ein wichtiger Bestandteil der Unterstützung für hohe Parallelität.

Es macht keinen Sinn, Funktionen einfach gleichzeitig auszuführen. Daten müssen zwischen Funktionen ausgetauscht werden, um die Bedeutung der gleichzeitigen Ausführung von Funktionen widerzuspiegeln.

Wenn eine Goroutine ein gleichzeitig ausgeführter Hauptteil eines Go-Programms ist, channelist sie die Verbindung zwischen ihnen. channelEin Kommunikationsmechanismus, der es einer Goroutine ermöglicht, bestimmte Werte an eine andere Goroutine zu senden.

Darüber hinaus müssen Sie die Concurrency-Philosophie von go genau kennen und dieses Prinzip im Hinterkopf behalten: Verwenden Sie Kommunikation, um Speicher zu teilen, verwenden Sie keinen gemeinsamen Speicher, um zu kommunizieren.

Nachdem wir die Rolle des Kanals herausgefunden haben, wollen wir die Eigenschaften von gqueue im GoFrame-Framework (im Folgenden als gf bezeichnet) untersuchen.

warten

Konzept

Warteschlange gqueue Gleichzeitig sichere Warteschlange mit dynamischer Größe

gqueue kann auch auf eine Warteschlange mit fester Größe eingestellt werden, was sich nicht vom Standardbibliothekskanal unterscheidet, wenn die Größe fest ist.

Einfach ausgedrückt, die von channel implementierte Funktion kann auch von gqueue implementiert werden.

zu verwendende Szenen:

gqueue ist nebenläufigkeitssicher und wird häufig in Szenarien verwendet, in denen mehrere Goroutinen Daten kommunizieren und dynamische Warteschlangengrößen unterstützen

Code-Demo

package main

import (
   "fmt"
   "github.com/gogf/gf/container/gqueue"
   "github.com/gogf/gf/os/gtimer"
   "time"
)

func main() {
   //实例化gqueue
   q := gqueue.New()
   //数据生产者 每隔1秒想队列写入1条数据
   gtimer.SetInterval(time.Second, func() {
      nowStr := time.Now().String()
      q.Push(nowStr)
   })

   //3秒后关闭队列
   gtimer.SetTimeout(time.Second*3, func() {
      fmt.Println("关闭队列")
      q.Close()
   })

   // 消费者 不停的从队列中取值输出到终端中
   for {
      if v := q.Pop(); v != nil {
         fmt.Println("消费者接收:", v)
      } else {
         break
      }
   }
}
复制代码

Ergebnis drucken

Bild.png

Vorteil

Warum nicht den Kanal der Standardbibliothek verwenden, sondern gqueue verwenden?

  1. Die Verwendung von gqueue ist flexibler als Kanal, Kanal hat eine Begrenzung der Warteschlangengröße und gqueue-Warteschlange unterstützt dynamische Größe

  2. Die Lese- und Schreibleistung des Kanals ist zwar sehr hoch, aber der Speicher muss initialisiert werden, wenn der Kanal erstellt wird, und die Effizienz des Initialisierungsvorgangs ist sehr gering, während die Erstellungseffizienz von gqueue sehr hoch ist und gqueue Speicher dynamisch erstellt .

Low-Level-Implementierung

Die zugrunde liegende Implementierung von gqueue basiert auf der dynamischen Größe von glist. Das Lesen von Daten wird blockiert, wenn die Warteschlange voll oder die Warteschlange leer ist.

Glist ist ein parallelitätssicherer Link, der das Deaktivieren der parallelitätssicheren Funktion unterstützt. Wenn die parallelitätssichere Funktion deaktiviert ist, ist sie dasselbe wie eine gewöhnliche verknüpfte Liste, und es gibt keine Blockierung beim Speichern und Lesen von Daten.

verhindern, dass der Prozess zerstört wird

Die Rolle von select{} kann verhindern, dass der Prozess zerstört wird

package main

import (
   "fmt"
   "github.com/gogf/gf/container/gqueue"
   "github.com/gogf/gf/os/gtime"
   "github.com/gogf/gf/os/gtimer"
   "time"
)

func main() {
   //实例化队列
   queue := gqueue.New()
   // 生产者每隔1秒钟向队列写入一条数据
   gtimer.SetInterval(time.Second, func() {
      queue.Push(gtime.Now().String())
   })
   //消费者 常驻内存一直接收生产者的数据
   for {
      select {
      case v := <-queue.C: //C是 chan interface{}
         if v != nil {
            fmt.Println("消费者:", v)
         } else {
            return
         }
      }
   }
}
复制代码

Operationsergebnis

Wie in der Abbildung unten gezeigt, kann select{} verhindern, dass der Prozess zerstört wird, gtimer hat Daten produziert und select in der for-Schleife hat Daten verbraucht.

Bild.png

Zusammenfassen

Durch diesen Artikel kennen wir das Konzept und die Rolle des Kanals. Ich kenne auch die zugrunde liegende Implementierung und Eigenschaften von gqueue sowie den Vergleich zwischen gqueue und channel. Welche Eigenschaften haben beide.

zu guter Letzt

Danke fürs Lesen und heiße alle willkommen: like, favorite,Münze(konzentrieren Sie sich auf)! ! !

8e95dac1fd0b2b1ff51c08757667c47a.gif

Ich denke du magst

Origin juejin.im/post/7103502362429358116
Empfohlen
Rangfolge