golang 写任务队列
🕘 Mon, 20 Mar 2017 by GolangNote
golang 写任务队列
package main
import (
"flag"
"fmt"
"net/http"
"time"
)
var (
NWorkers = flag.Int("n", 4, "The number of workers to start")
HTTPAddr = flag.String("http", "127.0.0.1:8000", "Address to listen for HTTP requests on")
)
type WorkRequest struct {
Name string
Delay time.Duration
}
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())
}
}
// ---------The collector ---
// A buffered channel that we can send work requests on.
var WorkQueue = make(chan WorkRequest, 100)
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() < 1 || delay.Seconds() > 10 {
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
}
// ------ The worker
// 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
}()
}
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 := 0; i < nworkers; i++ {
fmt.Println("Starting worker", i+1)
worker := NewWorker(i+1, 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
}()
}
}
}()
}
本文网址: https://golangnote.com/topic/158.html (转载注明出处)
关于GolangNote:记录在工作中使用golang 遇到、面临的相关问题及解决方法。如果你在这里获得一些知识或信息,解决你的编程问题,请考虑捐赠给不幸的人或者你喜欢的慈善机构,除捐赠外,种植树木、志愿服务或减少排碳的行为也很有益处。如果你有任何问题可以在下面 留言
Be the first to comment!
Relative Articles
Recent Go Articles
- Golang 把cookie 字符串解析为cookie 结构
- Golang 计算字符串中包含某个或某些字符集的个数
- 使用Golang 对文件增删写读操作备忘
- Go Modules 使用备忘
- 使用Golang 简单删除图片exif 信息
- 谷歌翻译的 golang 库推荐
- Go 1.13.2 与1.13.3 紧急更新
- golang 人脸检测识别库
- Go build 错误 “stackcheck redeclared in this block previous declaration”的解决方法
- Golang phantomjs 动态代理实现
- Golang chrome debug protocol 库推荐
- Golang 随机打乱数组/Slice
- Golang sync.WaitGroup 的 Wait 超时处理
- Golang实现简单的Socks5代理
- Golang 用snappy + Base64 简单压缩加密进行网络传输
- Golang http IPv4/IPv6 服务
- golang 全角半角相互转换
- 在自己的网站部署TLS 1.3
- Golang 实现/打印菜单树
- Golang telegram 机器人小试
Top Go Articles
- Golang实现简单的Socks5代理
- goLang 实现排列组合的代码
- 用Go语言写一个最简单的echo服务器
- golang 用正则包regexp 通过user-agent 识别手机浏览器
- Go build 错误 “stackcheck redeclared in this block previous declaration”的解决方法
- Golang 字符串毫秒转时间格式
- Golang 简单的任务队列
- Golang telegram 机器人小试
- Golang 定时循环的实现
- golang 用 crypto/bcrypt 存储密码的例子
- Golang 生成防识别的图片验证码
- golang 实现Authenticator 二次验证,可用到web 登录
- golang 为Windows XP/Server 2003 编译程序
- Golang io.ReadCloser 和[]byte 相互转化的方法
- groupcache 使用入门
- golang 用gzip 压缩、解压缩字符串
- chroma: 纯go 实现的类似Pygments 的代码高亮库
- golang flate/zlib 解压缩
- golang 生成良好的唯一ID/uuid库比较
- Golang 生成 session id