ホームページ  >  記事  >  バックエンド開発  >  golang パイプライン実装キュー

golang パイプライン実装キュー

WBOY
WBOYオリジナル
2023-05-15 09:02:36468ブラウズ

概要

業界で人気のプログラミング言語として、Golang には軽量、同時実行の安全性、組み込み GC、高速コンパイルなどの利点があり、クラウド コンピューティング、Web、ウェブ クローラーやその他の分野。 Golang の効率的な同時実行モデルは、Golang が人気がある理由の 1 つです。パイプライン機構は Golang の同時実行機構の 3 つの通信方式の 1 つで、パイプラインはバッファなしパイプとバッファ付きパイプに分けられます。

Golang の同時実行モデルでは、通常、プロデューサーとコンシューマー間の通信メカニズムを実装するためにパイプラインが使用されます。プロデューサーがデータを大量に入力すると、コンシューマーはパイプラインからデータを取得して処理できます。このモデルでは、パイプはキューとして機能します。したがって、Golang のパイプライン機構はキューの実装にも適しています。

この記事では、Golang のパイプライン メカニズムを使用してキューを実装する方法を紹介します。具体的には、同時実行をサポートするバッファ付きキューを作成し、バッファなしパイプを使用して境界付きキューを実装する方法を簡単に説明します。

バッファ付きパイプを使用したキュー

バッファ付きパイプを使用したキューを使用すると、生産/消費の速度が一貫していない場合でも、生産者/消費者は通常どおりに動作できます。サイズは固定されており、キューがいっぱいの場合はプロデューサーがブロックされ、キューが空の場合はコンシューマーがブロックされます。 Golang では、make() 関数を使用してバッファリングされたパイプを作成できます。

以下は簡単な実装例です:

package main

import "fmt"

type Queue struct {
    // 声明管道
    items chan int
    // 声明队列最大容量
    capacity int
}

func NewQueue(capacity int) *Queue {
    return &Queue{make(chan int, capacity), capacity}
}

func (q *Queue) Enqueue(item int) {
    q.items <- item
}

func (q *Queue) Dequeue() int {
    return <-q.items
}

func main() {
    q := NewQueue(3)

    q.Enqueue(1)
    q.Enqueue(2)
    q.Enqueue(3)

    fmt.Println(q.Dequeue()) // 1
    fmt.Println(q.Dequeue()) // 2
    fmt.Println(q.Dequeue()) // 3
}

上記のコードでは、パイプとキューの最大容量を含むキューを表す構造体を使用しています。 NewQueue() 関数は、指定された最大容量を持つキューを作成するために使用されます。 Enqueue() 関数では、パイプにデータを書き込み、パイプがいっぱいの場合はブロックします。 Dequeue() 関数では、パイプからデータを読み取り、パイプが空の場合はブロックします。 main() 関数では、最大容量 3 のキューを作成し、3 つの要素 1、2、および 3 をキューに追加します。次に、Dequeue() 関数が順番に呼び出され、キューから要素が取得され、コンソールに出力されます。

境界付きキューを実装するためのバッファーなしパイプ

Golang では、バッファーなしパイプを使用して境界付きキューを実装するには、select ステートメント メカニズムを使用する必要があります。 select ステートメントでデフォルト ステートメントを使用すると、キューがいっぱいまたは空の場合のブロック状況を処理できます。

次は、バッファなしパイプを使用して境界付きキューを実装する例です。

package main

import (
    "fmt"
    "math/rand"
)

type Queue struct {
    items chan int
}

func NewQueue() *Queue {
    return &Queue{make(chan int)}
}

func (q *Queue) Enqueue(item int) {
    select {
    case q.items <- item:
    default:
        <-q.items
        q.items <- item
    }
}

func (q *Queue) Dequeue() int {
    select {
    case item := <-q.items:
        return item
    default:
        return -1
    }
}

func main() {
    q := NewQueue()

    for i := 0; i < 10; i++ {
        go func() {
            q.Enqueue(rand.Intn(100))
        }()

        go func() {
            fmt.Println(q.Dequeue())
        }()
    }
}

上記のコードでは、構造体を使用して境界付きキューを表します。バッファ付きパイプとは異なり、パイプの作成時にキューの最大容量を渡しません。 Enqueue() 関数では、パイプがいっぱいではないときに select ステートメントを使用して要素を挿入します。パイプがいっぱいの場合は、デフォルトの条件を使用して、最初に現在のキューの最初の要素をパイプから削除します。追加 新しい要素が挿入されます。また、Dequeue() 関数は、パイプが空でない場合に select ステートメントを使用してキュー内の最初の要素を返します。パイプが空の場合は、デフォルトのケースが使用され、-1 が返されます。

main() 関数では、10 個の要素をキューに挿入し、10 個のコルーチンを使用してキュー内の要素をそれぞれデキューします。キューの容量が 1 であるため、Enqueue() 関数はキューに要素を継続的に挿入し、キューが空でない場合は Dequeue() 関数は要素を継続的に削除していることがわかります。したがって、出力は一連のランダムな整数になります。

結論

この記事の導入部を通じて、Golang パイプライン メカニズムを使用してキューを実装するのが非常に簡単であることがわかります。バッファー付きパイプを備えたキューの場合、その最大容量は make() 関数で直接指定できますが、バッファーなしパイプで境界付きキューを実装するには、select ステートメント メカニズムを使用する必要があります。 Golang の同時実行モデルの利点により、Golang パイプライン メカニズムを使用してキューを実装するのが最も効率的です。

以上がgolang パイプライン実装キューの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。