什么是Actor模型闪朱?
Actor 模式是一個解決分布式計算的數(shù)學模型薛匪,其中 Actor 是基礎(chǔ)捐川,它能回應接收到消息,能夠自我決策逸尖,創(chuàng)建更多的 Actor古沥,發(fā)送更多的消息瘸右,決定如何回應下一個接收到的消息。Actor 認為一切皆是 Actor岩齿,類似于面向?qū)ο笳J為一切皆 Object 一樣太颤。OO 的執(zhí)行是順序的,Actor 模型內(nèi)在設(shè)計就是并行的盹沈。
Actor 是異步的
Actor 是計算實體龄章,它回復接收到的消息,能夠并行的:
- 發(fā)生有限的消息給其他 Actor
- 創(chuàng)建有限數(shù)目的新 Actor
- 指定一個消息到達時的行為
這些操作并沒有順序要求襟诸,它們能夠并行地實施瓦堵。由于沒有對消息的時序做規(guī)定,Actor 模式是一種異步模型歌亲,發(fā)送到 Actor 不等待消息被接收而繼續(xù)執(zhí)行菇用。Actor 之間不共享狀態(tài),如果想獲取其他 Actor 的狀態(tài)陷揪,只能通過消息請求的方式惋鸥。
Actor 在消息內(nèi)部指定接收消息的 Actor 地址。Actor 可以用自己的地址發(fā)送消息悍缠,相當于自己接收到自己發(fā)送的消息卦绣,可以驅(qū)動自己的狀態(tài)。
所謂真正的 Actor 模型
Actor 可以被認為是在用戶空間實現(xiàn)的并發(fā)實體飞蚓,所以它應該是應用級別的線程滤港。如果認同這個觀點那么 Actor 要滿足的要求 = 操作系統(tǒng)對進程/線程 提出的要求一樣。
內(nèi)存結(jié)構(gòu)
每個并發(fā)實體都是要有一個固定的數(shù)據(jù)結(jié)構(gòu)趴拧,必須有一個容器可以保存當前所有的并發(fā)實體溅漾。這一點基本上很容易滿足,Akka 中 Actor 就是一個類著榴,所以它的結(jié)構(gòu)就是這個類的數(shù)據(jù)結(jié)構(gòu)添履,大小也就是這個類的大小。Akka 中的 Dispatcher 保存有所有 Actor 的列表脑又。
并發(fā)原語
操作系統(tǒng)的是通過臨界區(qū)暮胧,鎖來定義多線程共享數(shù)據(jù)模型的。在 Actor 中是通過消息來共享數(shù)據(jù)的问麸⊥裕基于消息傳遞要求“數(shù)據(jù)只讀”,你發(fā)送出去的數(shù)據(jù)再修改肯定就不對了严卖。但是這一點在 Java 里面無論如何都是做不到的炼绘,你不修改變量的引用但是還可以修改變量里面的值,調(diào)用對象的方法妄田。
調(diào)度
這是最重要的:沒有調(diào)度俺亮,并發(fā)實體根本不能稱之為并發(fā)實體驮捍。操作系統(tǒng)中 CPU 是由內(nèi)核管理的,調(diào)度算法是基于時間片來調(diào)任務(wù)的脚曾,內(nèi)核隨時可以剝奪一個任務(wù)的 CPU 使用權(quán)這就是“搶占”东且。這一點非常重要,沒有這個功能就意味著調(diào)度是不公平的本讥。一個任務(wù)耗費大量 CPU 會把另個一任務(wù)給餓死珊泳。但是在用戶空間(應用層)很難實現(xiàn)這一點,畢竟 CPU 是不受應用程序的控制的拷沸,沒有把辦法剝奪色查。搶占看似可有可無,但是沒有它就沒有“公平調(diào)度”撞芍,也就談不上并發(fā)秧了。(有任務(wù)撐死,有任務(wù)餓死)
所謂“公平調(diào)度”
比如寫兩個 Actor序无,使用無限循環(huán)輸出字符串(while(true))會瘋狂的吃 CPU验毡,如果是可搶占的公平調(diào)度,則 actor1 和 actor2 應該是比較有規(guī)律的交替(大家得到的 CPU 時間差不多)
Java 中的 Akka
test1
test1
test1
...
test2
test2
test2
...
test1
...
ErLang
test1
test2
test1
test2
test1
test2
test1
test2
...
ErLang 非常均勻的任務(wù)切換帝嗡,實現(xiàn)了“可搶占的公平”晶通。