Future
是 java
中比较常见的并发编程解决方案,它采用异步的方式,尽可能减少运行时代码阻塞,很大程度上提高了程序的运行效率,在golang
中我们可以利用 goroutine
, chan
机制和 for select
轻松实现类似的功能。
其实 Future
的本质就是异步计算的结果,我们用 item interface{}
来放置 Future
的结果,通过读取 triggered
的值来判断异步计算是否已经返回。
New
方法用于构造 Future
任务,它通过监听 Completer
通道来获取异步执行的结果,如果监听超时,则停止监听,返回错误。
1 | type Future struct { |
listen
是获得异步计算结果的核心,如果 Completer
通道返回,则通过 set
方法设置计算结果,并标记 triggered
为 true
,如果监听超时,则同样标记 triggered
为 true
,但此时应该返回一个错误而非正确的计算结果。
1 | func listen(f *Future, ch Completer, timeout time.Duration) { |
因为 Future
返回结果的时机并不确定, 所以我们需要一种方式得知结果是否已经返回,IsDone
方法通过查询 triggered
是否为 true
来得知结果是否已经返回 ,也就是查询事件是否已经触发,这里结果返回和发生超时都可以触发事件。
1 | func (f *Future) IsDone() bool { |
所以无论是结果返回,还是超时发生,我们都要通过 set
方法对 Future
进行设置,来标记 Future
事件完成。设置完通过 f.wg.Done()
来通知所有等待此结果的监听者。
1 | func (f *Future) set(item interface{}, err error) { |
Get
方法用于获得 Future
执行的结果,如果此时 Future
已经触发,那么可以直接返回结果,但是如果此时 triggered
为 false
,也就是说那两件事件中一件都没有发生,此时我们只能傻傻地等待( f.wg.Wait()
) ,直到别人广播( f.wg.Done()
)来告知事件已经发生。
1 | func (f *Future) Get() (interface{}, error) { |
下面是应用 Future
的简单例子。
1 | completer := make(chan interface{}) |