Files
the-way-to-go_ZH_CN/eBook/14.15.md

60 lines
2.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 14.15 漏桶算法
(译者注:翻译遵照原文,但是对于完全没听过这个算法的人来说比较晦涩,请配合代码片段理解)
考虑以下的客户端-服务器结构:客户端协程执行一个无限循环从某个源头(也许是网络)接收数据;数据读取到 `Buffer` 类型的缓冲区。为了避免分配过多的缓冲区以及释放缓冲区,它保留了一份空闲缓冲区列表,并且使用一个缓冲通道来表示这个列表:`var freeList = make(chan *Buffer,100)`
这个可重用的缓冲区队列freeList与服务器是共享的。 当接收数据时,客户端尝试从 `freeList` 获取缓冲区;但如果此时通道为空,则会分配新的缓冲区。一旦消息被加载后,它将被发送到服务器上的 `serverChan` 通道:
```go
var serverChan = make(chan *Buffer)
```
以下是客户端的算法代码:
```go
func client() {
for {
var b *Buffer
// Grab a buffer if available; allocate if not
select {
case b = <-freeList:
// Got one; nothing more to do
default:
// None free, so allocate a new one
b = new(Buffer)
}
loadInto(b) // Read next message from the network
serverChan <- b // Send to server
}
}
```
服务器的循环则接收每一条来自客户端的消息并处理它,之后尝试将缓冲返回给共享的空闲缓冲区:
```go
func server() {
for {
b := <-serverChan // Wait for work.
process(b)
// Reuse buffer if there's room.
select {
case freeList <- b:
// Reuse buffer if free slot on freeList; nothing more to do
default:
// Free list full, just carry on: the buffer is 'dropped'
}
}
}
```
但是这种方法在 `freeList` 通道已满的时候是行不通的,因为无法放入空闲 `freeList` 通道的缓冲区会被“丢到地上”由垃圾收集器回收(故名:漏桶算法)
## 链接
- [目录](directory.md)
- 上一节:[并行化大量数据的计算](14.14.md)
- 下一节:[对 Go 协程进行基准测试](14.16.md)