go 多线程并发 queue demo
原文链接: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的更多相关文章
- java多线程并发执行demo,主线程阻塞
其中有四个知识点我单独罗列了出来,属于多线程编程中需要知道的知识: 知识点1:X,T为泛型,为什么要用泛型,泛型和Object的区别请看:https://www.cnblogs.com/xiaoxio ...
- Python2 socket 多线程并发 ThreadingTCPServer Demo
# -*- coding:utf-8 -*- from SocketServer import TCPServer, StreamRequestHandler import traceback cla ...
- Python2 socket 多线程并发 TCPServer Demo
#coding=utf-8 import socket import threading,getopt,sys,string opts, args = getopt.getopt(sys.argv[1 ...
- 用Queue控制python多线程并发数量
python多线程如果不进行并发数量控制,在启动线程数量多到一定程度后,会造成线程无法启动的错误. 下面介绍用Queue控制多线程并发数量的方法(python3). # -*- coding: utf ...
- 多线程并发执行任务,取结果归集。终极总结:Future、FutureTask、CompletionService、CompletableFuture
目录 1.Futrue 2.FutureTask 3.CompletionService 4.CompletableFuture 5.总结 ================正文分割线========= ...
- java中并发Queue种类与各自API特点以及使用场景!
一 先说下队列 队列是一种数据结构.它有两个基本操作:在队列尾部加入一个元素,和从队列头部移除一个元素(注意不要弄混队列的头部和尾部) 就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经 ...
- Java多线程-并发容器
Java多线程-并发容器 在Java1.5之后,通过几个并发容器类来改进同步容器类,同步容器类是通过将容器的状态串行访问,从而实现它们的线程安全的,这样做会消弱了并发性,当多个线程并发的竞争容器锁的时 ...
- python多进程并发和多线程并发和协程
为什么需要并发编程? 如果程序中包含I/O操作,程序会有很高的延迟,CPU会处于等待状态,这样会浪费系统资源,浪费时间 1.Python的并发编程分为多进程并发和多线程并发 多进程并发:运行多个独立的 ...
- Java多线程并发编程一览笔录
线程是什么? 线程是进程中独立运行的子任务. 创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该 ...
随机推荐
- SQLyog无操作一段时间后重新操作会卡死问题(解决办法)
这种是因为一段时间不操作后,服务器将空闲连接丢弃了,而客户端(sqlyog)不知道,导致长时间无响应,而超时之后,sqlyog 使用了新的连接,所以又可以顺畅操作了. 将会话空闲时间默认改为自定义,填 ...
- 1-Numpy的通用函数(ufunc)
一.numpy“通用函数”(ufunc)包括以下几种: 元素级函数(一元函数):对数组中的每个元素进行运算 数组级函数:统计函数,像聚合函数(例如:求和.求平均) 矩阵运算 随机生成函数 常用一元通用 ...
- PHP printf() 函数
实例 输出格式化的字符串: <?php高佣联盟 www.cgewang.com$number = 9;$str = "Beijing";printf("There ...
- QDC day4
图论. 强连通图 与 弱连通图 . 最短路 .dij 不支持负权.显然 值得一提的是利用斐波那契堆m+nlogn . 一张 边权都是2的整数次幂 考虑 一下直接 结构体维护这个2的整次幂数组但比大小 ...
- Spark Streaming高吞吐、高可靠的一些优化
分享一些Spark Streaming在使用中关于高吞吐和高可靠的优化. 目录 1. 高吞吐的优化方式 1.1 更改序列化的方式 1.2 修改Receiver接受到的数据的存储级别 1.3 广播配置变 ...
- MapReduce之GroupingComparator分组(辅助排序、二次排序)
指对Reduce阶段的数据根据某一个或几个字段进行分组. 案例 需求 有如下订单数据 现在需要找出每一个订单中最贵的商品,如图 需求分析 利用"订单id和成交金额"作为key,可以 ...
- wps 2011 破解版软件
今天换了一台新电脑. wps 都没有 系统的太过忍受不了 整了一天终于是找到了一个合适安装的 想要的邮件发给我 673658917@qq.com
- MySQL8.0.20安装配置+用Navicat连接详细教程(win10,Navicat15)
MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用 ...
- 标星7000+,这个 Python 艺术二维码生成器厉害了!
微信二维码,相信大家也并不陌生,为了生成美观的二维码,许多用户都会利用一些二维码生成工具. 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手 ...
- 【av68676164(p41-p42)】内存管理功能
存储器的功能需求 容量足够大 速度足够快 信息永久保存 多道程序并行 多道程序并行带来的问题 共享:代码和数据共享,节省内存 保护:不允许内存中的程序相互间非法访问 实际存储器体系 三级存储体系 Ca ...