將輸入視為消息還是閉包

[b]法一[/b]

如果當作閉包理解,接收函數效果大致如下:


function recv(msg){
actionQueue.push(function(state, msg){ return function(){
//TODO howto handle this message;
}}(this, msg))
}


這個做法可以取到串行的效果,且接收消息時立即提交處理過程到隊列,看起來較為乾淨。

但如果 this 為值類型數據,當遇到幷發時,前一處理過程和後一過程將在同一個狀態上加工,會發生覆寫。

[b]法二[/b]

如將該處理器設計為反哺的方式:


function recv(msg){
actionQueue.push(function(state){
//TODO howto handle this message
return new_state;
})
}


如上,處理隊列存儲的處理器接受一個參數 state,msg 因閉包帶進了處理器。在外部,需要一個推進 actionQuue 的調用:


var s1 = actionQueue.pop()(s0);
s1 = actionQueue.pop()(s1);
s1 = actionQueue.pop()(s1);
// so on



[b]法三[/b]
消息隊列的使用方式大致如下:


var msg = actionQueue.pop();
var state = getState();
var state2 = handle(msg, state);
saveState(sate2);

var msg = actionQueue.pop();
var state = getState();
var state2 = handle(msg, state);
saveState(sate2);

// so on



這種方式使用相同的 handle 函數,因此它需要在一個 handle 中編寫所有處理邏輯。在函數處理語言中,會採用匹配方式使代碼看起來漂亮一些,當然,也會分出幾個子過程。如果是 java,還可能分出好些個類來。

[b]法四[/b]
erlang 採用的方式是在等待消息前,先將處理過程、狀態壓棧,在收到消息後,將處理過程、狀態取出,讓處理過程處理狀態和消息。採用上面的寫法,大致如下:



// at first
process.hang(pid, {handle : someHandle, state : state})


function recv(pid, msg){
var p = process.get(pid);
p.handle(p.state, msg);
}

// if handler want loop
functiion someHandle(state, msg){
// TODO handle and handle ...

process.hang(pid, {handle : nextHandle, state : newState}
}



[b]結論[/b]

考慮到函數的閉包特性,法二和法四具備相當的效果。但值得注意的是,法二屬於通常性質上的延後處理,法四貌似收到即處理,但在接收和處理之間,同樣有個投遞的過程。對於不具備切換和管理進程的平臺,法二是一個不錯的選擇,另外,法二還不需要設計信箱機制。

消息隊列的做法本身完全可行,做進程遷移更顯輕鬆,但它容易導致比較分散的代碼,容易演變為狀態機。

綜上,在 Java 平臺,使用法二是一個不錯的選擇。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值