原文链接:Writing worker queues, in Go

1.work.go

[root@wangjq queue]# cat work.go
package main import "time" type WorkRequest struct {
Name string
Delay time.Duration
}

2.collector.go

[root@wangjq queue]# cat collector.go
package main import (
"fmt"
"net/http"
"time"
) // A buffered channel that we can send work requests on.
var WorkQueue = make(chan WorkRequest, ) func Collector(w http.ResponseWriter, r *http.Request) {
// Make sure we can only be called with an HTTP POST request.
if r.Method != "POST" {
w.Header().Set("Allow", "POST")
w.WriteHeader(http.StatusMethodNotAllowed)
return
} // Parse the delay.
delay, err := time.ParseDuration(r.FormValue("delay"))
if err != nil {
http.Error(w, "Bad delay value: "+err.Error(), http.StatusBadRequest)
return
} // Check to make sure the delay is anywhere from 1 to 10 seconds.
if delay.Seconds() < || delay.Seconds() > {
http.Error(w, "The delay must be between 1 and 10 seconds, inclusively.", http.StatusBadRequest)
return
} // Now, we retrieve the person's name from the request.
name := r.FormValue("name") // Just do a quick bit of sanity checking to make sure the client actually provided us with a name.
if name == "" {
http.Error(w, "You must specify a name.", http.StatusBadRequest)
return
} // Now, we take the delay, and the person's name, and make a WorkRequest out of them.
work := WorkRequest{Name: name, Delay: delay} // Push the work onto the queue.
WorkQueue <- work
fmt.Println("Work request queued") // And let the user know their work request was created.
w.WriteHeader(http.StatusCreated)
return
}

3.worker.go

[root@wangjq queue]# cat worker.go
package main import (
"fmt"
"time"
) // NewWorker creates, and returns a new Worker object. Its only argument
// is a channel that the worker can add itself to whenever it is done its
// work.
func NewWorker(id int, workerQueue chan chan WorkRequest) Worker {
// Create, and return the worker.
worker := Worker{
ID: id,
Work: make(chan WorkRequest),
WorkerQueue: workerQueue,
QuitChan: make(chan bool)} return worker
} type Worker struct {
ID int
Work chan WorkRequest
WorkerQueue chan chan WorkRequest
QuitChan chan bool
} // This function "starts" the worker by starting a goroutine, that is
// an infinite "for-select" loop.
func (w *Worker) Start() {
go func() {
for {
// Add ourselves into the worker queue.
w.WorkerQueue <- w.Work select {
case work := <-w.Work:
// Receive a work request.
fmt.Printf("worker%d: Received work request, delaying for %f seconds\n", w.ID, work.Delay.Seconds()) time.Sleep(work.Delay)
fmt.Printf("worker%d: Hello, %s!\n", w.ID, work.Name) case <-w.QuitChan:
// We have been asked to stop.
fmt.Printf("worker%d stopping\n", w.ID)
return
}
}
}()
} // Stop tells the worker to stop listening for work requests.
//
// Note that the worker will only stop *after* it has finished its work.
func (w *Worker) Stop() {
go func() {
w.QuitChan <- true
}()
}

4.dispatcher.go

[root@wangjq queue]# cat dispatcher.go
package main import "fmt" var WorkerQueue chan chan WorkRequest func StartDispatcher(nworkers int) {
// First, initialize the channel we are going to but the workers' work channels into.
WorkerQueue = make(chan chan WorkRequest, nworkers) // Now, create all of our workers.
for i := ; i < nworkers; i++ {
fmt.Println("Starting worker", i+)
worker := NewWorker(i+, WorkerQueue)
worker.Start()
} go func() {
for {
select {
case work := <-WorkQueue:
fmt.Println("Received work requeust")
go func() {
worker := <-WorkerQueue fmt.Println("Dispatching work request")
worker <- work
}()
}
}
}()
}

5.main.go

[root@wangjq queue]# cat main.go
package main import (
"flag"
"fmt"
"net/http"
) var (
NWorkers = flag.Int("n", , "The number of workers to start")
HTTPAddr = flag.String("http", "127.0.0.1:8000", "Address to listen for HTTP requests on")
) func main() {
// Parse the command-line flags.
flag.Parse() // Start the dispatcher.
fmt.Println("Starting the dispatcher")
StartDispatcher(*NWorkers) // Register our collector as an HTTP handler function.
fmt.Println("Registering the collector")
http.HandleFunc("/work", Collector) // Start the HTTP server!
fmt.Println("HTTP server listening on", *HTTPAddr)
if err := http.ListenAndServe(*HTTPAddr, nil); err != nil {
fmt.Println(err.Error())
}
}

6.编译

[root@wangjq queue]# go build -o queued *.go

7.运行

[root@wangjq queue]# ./queued -n
Starting the dispatcher
Starting worker
Starting worker
Starting worker
Starting worker
Starting worker
Registering the collector
HTTP server listening on 127.0.0.1:

8.测试

[root@wangjq ~]# for i in {..}; do curl localhost:/work -d name=$USER -d delay=$(expr $i % )s; done

9.效果

[root@wangjq queue]# ./queued -n
Starting the dispatcher
Starting worker
Starting worker
Starting worker
Starting worker
Starting worker
Registering the collector
HTTP server listening on 127.0.0.1:
Work request queued
Received work requeust
Dispatching work request
worker1: Received work request, delaying for 1.000000 seconds
Work request queued
Received work requeust
Dispatching work request
worker2: Received work request, delaying for 2.000000 seconds
Work request queued
Received work requeust
Dispatching work request
worker4: Received work request, delaying for 3.000000 seconds
worker1: Hello, root!
worker2: Hello, root!
worker4: Hello, root!

go 多线程并发 queue demo的更多相关文章

  1. java多线程并发执行demo,主线程阻塞

    其中有四个知识点我单独罗列了出来,属于多线程编程中需要知道的知识: 知识点1:X,T为泛型,为什么要用泛型,泛型和Object的区别请看:https://www.cnblogs.com/xiaoxio ...

  2. Python2 socket 多线程并发 ThreadingTCPServer Demo

    # -*- coding:utf-8 -*- from SocketServer import TCPServer, StreamRequestHandler import traceback cla ...

  3. Python2 socket 多线程并发 TCPServer Demo

    #coding=utf-8 import socket import threading,getopt,sys,string opts, args = getopt.getopt(sys.argv[1 ...

  4. 用Queue控制python多线程并发数量

    python多线程如果不进行并发数量控制,在启动线程数量多到一定程度后,会造成线程无法启动的错误. 下面介绍用Queue控制多线程并发数量的方法(python3). # -*- coding: utf ...

  5. 多线程并发执行任务,取结果归集。终极总结:Future、FutureTask、CompletionService、CompletableFuture

    目录 1.Futrue 2.FutureTask 3.CompletionService 4.CompletableFuture 5.总结 ================正文分割线========= ...

  6. java中并发Queue种类与各自API特点以及使用场景!

    一 先说下队列 队列是一种数据结构.它有两个基本操作:在队列尾部加入一个元素,和从队列头部移除一个元素(注意不要弄混队列的头部和尾部) 就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经 ...

  7. Java多线程-并发容器

    Java多线程-并发容器 在Java1.5之后,通过几个并发容器类来改进同步容器类,同步容器类是通过将容器的状态串行访问,从而实现它们的线程安全的,这样做会消弱了并发性,当多个线程并发的竞争容器锁的时 ...

  8. python多进程并发和多线程并发和协程

    为什么需要并发编程? 如果程序中包含I/O操作,程序会有很高的延迟,CPU会处于等待状态,这样会浪费系统资源,浪费时间 1.Python的并发编程分为多进程并发和多线程并发 多进程并发:运行多个独立的 ...

  9. Java多线程并发编程一览笔录

    线程是什么? 线程是进程中独立运行的子任务. 创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该 ...

随机推荐

  1. SQLyog无操作一段时间后重新操作会卡死问题(解决办法)

    这种是因为一段时间不操作后,服务器将空闲连接丢弃了,而客户端(sqlyog)不知道,导致长时间无响应,而超时之后,sqlyog 使用了新的连接,所以又可以顺畅操作了. 将会话空闲时间默认改为自定义,填 ...

  2. 1-Numpy的通用函数(ufunc)

    一.numpy“通用函数”(ufunc)包括以下几种: 元素级函数(一元函数):对数组中的每个元素进行运算 数组级函数:统计函数,像聚合函数(例如:求和.求平均) 矩阵运算 随机生成函数 常用一元通用 ...

  3. PHP printf() 函数

    实例 输出格式化的字符串: <?php高佣联盟 www.cgewang.com$number = 9;$str = "Beijing";printf("There ...

  4. QDC day4

    图论. 强连通图 与 弱连通图 . 最短路 .dij 不支持负权.显然 值得一提的是利用斐波那契堆m+nlogn . 一张 边权都是2的整数次幂 考虑 一下直接 结构体维护这个2的整次幂数组但比大小 ...

  5. Spark Streaming高吞吐、高可靠的一些优化

    分享一些Spark Streaming在使用中关于高吞吐和高可靠的优化. 目录 1. 高吞吐的优化方式 1.1 更改序列化的方式 1.2 修改Receiver接受到的数据的存储级别 1.3 广播配置变 ...

  6. MapReduce之GroupingComparator分组(辅助排序、二次排序)

    指对Reduce阶段的数据根据某一个或几个字段进行分组. 案例 需求 有如下订单数据 现在需要找出每一个订单中最贵的商品,如图 需求分析 利用"订单id和成交金额"作为key,可以 ...

  7. wps 2011 破解版软件

    今天换了一台新电脑. wps 都没有 系统的太过忍受不了 整了一天终于是找到了一个合适安装的 想要的邮件发给我  673658917@qq.com

  8. MySQL8.0.20安装配置+用Navicat连接详细教程(win10,Navicat15)

    MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用 ...

  9. 标星7000+,这个 Python 艺术二维码生成器厉害了!

    微信二维码,相信大家也并不陌生,为了生成美观的二维码,许多用户都会利用一些二维码生成工具. 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手 ...

  10. 【av68676164(p41-p42)】内存管理功能

    存储器的功能需求 容量足够大 速度足够快 信息永久保存 多道程序并行 多道程序并行带来的问题 共享:代码和数据共享,节省内存 保护:不允许内存中的程序相互间非法访问 实际存储器体系 三级存储体系 Ca ...