真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Akka學(xué)習(xí)(五)消息傳遞的方式-創(chuàng)新互聯(lián)

目錄
  • 一 消息傳遞方式
    • 1.1 消息不可變
    • 1.2 ASK消息模式
    • 1.3 Tell消息模式
    • 1.4 Forward消息模式
    • 1.4 Pipe消息模式

有4種核心的Actor消息模式:tell、ask、forward和pipe。我們已經(jīng)了解過(guò)tell和ask,不過(guò)sender()都不是Actor。

創(chuàng)新互聯(lián)建站是專業(yè)的愛(ài)民網(wǎng)站建設(shè)公司,愛(ài)民接單;提供網(wǎng)站建設(shè)、成都做網(wǎng)站,網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行愛(ài)民網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!一 消息傳遞方式


在這里,將從Actor之間發(fā)送消息的角度來(lái)介紹所有關(guān)于消息傳遞的概念。
● Ask:向Actor發(fā)送一條消息,返回一個(gè)Future。當(dāng)Actor返回響應(yīng)時(shí),會(huì)完成Future。不會(huì)向消息發(fā)送者的郵箱返回任何消息。
● Tell。向Actor發(fā)送一條消息。所有發(fā)送至sender()的響應(yīng)都會(huì)返回給發(fā)送消息的Actor?!?Forward:將接收到的消息再發(fā)送給另一個(gè)Actor。所有發(fā)送至sender()的響應(yīng)都會(huì)返回給原始消息的發(fā)送者。
● Pipe:用于將Future的結(jié)果返回給sender()或另一個(gè)Actor。如果正在使用Ask或是處理一個(gè)Future,那么使用Pipe可以正確地返回Future的結(jié)果。

1.1 消息不可變
  • 前面提到過(guò),消息應(yīng)該是不可變的,由于Akka基于JVM,而Java和Scala都支持可變類型,所以是有可能發(fā)送可變消息的。
  • 不過(guò)如果這么做,就可能會(huì)失去Akka在消除共享狀態(tài)方面提供的諸多益處,一旦有了可變消息,就引入了一種風(fēng)險(xiǎn):開(kāi)發(fā)者可能會(huì)在某些時(shí)候開(kāi)始修改消息,而他們修改消息的方式可能會(huì)破壞應(yīng)用程序的運(yùn)行。
  • 當(dāng)然,如果不修改消息的狀態(tài),那么要安全地使用可變消息也不是不可能,不過(guò)最好還是使用不可變消息,確保不會(huì)因?yàn)槲磥?lái)的變化而引入錯(cuò)誤。

可變消息定義

// Java
public class Message {public StringBuffer mutableBuffer;
            public Message(StringBuffer: mutableBuffer) {this.mutableBuffer = mutableBuffer;
            }
        }
// scala
class Message(var mutableBuffer: StringBuffer = new StringBuffer);
Message message = new Message(new StringBuffer("original"));
        message.mutableBuffer = new StringBuffer("new");

        val message = new Message(new StringBuffer("original"))
        message.mutableBuffer = new StringBuffer("new")

這個(gè)例子新建了一條消息,然后修改mutableBuffer引用,使之指向另一個(gè)新建的StringBuffer,消息創(chuàng)建時(shí)傳入的是StringBuffer (“original”),后來(lái)被修改成了StringBuffer(“new”)。這就是通過(guò)修改引用來(lái)修改消息的方法。
epub_22651331_25.jpg

消息不可變

public class Message {// final 
            public final StringBuffer mutableBuffer;

            Message(StringBuffer mutableBuffer) {this.mutableBuffer = mutableBuffer;
            }
        }
  • 在Scala中,如果沒(méi)有在聲明中給出任何訪問(wèn)修飾符,成員變量的引用默認(rèn)就是不可變的val。
  • 現(xiàn)在我們Java中加入Final關(guān)鍵字,可以使引用設(shè)置為不可變,但是會(huì)出現(xiàn)問(wèn)題,StringBuffer是可變的,因此可以修改修改StringBuffer對(duì)象本身。
public class ImmutableMessage{public final String immutableType;
            public ImmutableMessage(String immutableType) {this.immutableType = immutableType;
            }
        }
        class ImmutableMessage(immutableType: String)
  • 由于String是不可變類型,因此可以通過(guò)使用String代替StringBuffer使得消息不可變。

總結(jié)

理解不可變性不僅僅對(duì)于Akka消息是至關(guān)重要的,對(duì)于如何進(jìn)行安全的通用并發(fā)編程也是必不可少的,因此,無(wú)論什么時(shí)候,只要需要在線程之間共享數(shù)據(jù),就應(yīng)該首先考慮將數(shù)據(jù)定義為不可變。

1.2 ASK消息模式

![epub_22651331_27.jpg](https://img-blog.csdnimg.cn/img_convert/2a7e44802270d65d74f4b6588fff8522.jpeg

  • 在調(diào)用ask向Actor發(fā)起請(qǐng)求時(shí),Akka實(shí)際上會(huì)在Actor系統(tǒng)中創(chuàng)建一個(gè)臨時(shí)Actor。
  • 接收請(qǐng)求的Actor在返回響應(yīng)時(shí)使用的sender()引用就是這個(gè)臨時(shí)Actor。
  • 當(dāng)一個(gè)Actor接收到ask請(qǐng)求發(fā)來(lái)的消息并返回響應(yīng)時(shí),這個(gè)臨時(shí)Actor會(huì)使用返回的響應(yīng)來(lái)完成Future。
  • 因?yàn)閟ender()引用就指向臨時(shí)Actor的路徑,所以Akka知道要用哪個(gè)消息來(lái)完成Future。

要求

Ask模式要求定義一個(gè)超時(shí)參數(shù),如果對(duì)方?jīng)]有在超時(shí)參數(shù)限定的時(shí)間內(nèi)返回這個(gè)ask的響應(yīng),那么Future就會(huì)返回失敗。ask/?方法要求提供的超時(shí)參數(shù)可以是長(zhǎng)整型的毫秒數(shù),也可以是akka.util.Timeout,這種類型提供了更豐富的時(shí)間表達(dá)方式。
![epub_22651331_29.jpg](https://img-blog.csdnimg.cn/img_convert/50dcf9f3caa3978e58df33c9ff7b4690.jpeg#averageHue=#f0f0f0&clientId=uac482df2-4a9a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=278&id=ue3790d29&margin=[object Object]&name=epub_22651331_29.jpg&originHeight=347&originWidth=1198&originalType=binary&ratio=1&rotation=0&showTitle=false&size=44177&status=done&style=none&taskId=uc3ef683b-00ce-4632-86a0-8a7a71984e3&title=&width=958.4)

  • Java模式
static import akka.pattern.Patterns.ask;

Timeout timeout = new akka.util.Timeout(
    1,
    java.util.concurrent.TimeUnit.SECONDS
);
Future future = ask(actor, message, timeout);
  • Scala
import scala.concurrent.duration._
import akka.pattern.ask
// 設(shè)置超時(shí)時(shí)間
implicit val timeout = akka.util.Timeout(1 second)
val future = actorRef ? "message"

案例:請(qǐng)參考前面的案例3

缺點(diǎn)

Ask模式看上去很簡(jiǎn)單,不過(guò)它是有隱藏的額外性能開(kāi)銷的,首先,ask會(huì)導(dǎo)致Akka在/temp路徑下新建一個(gè)臨時(shí)Actor。
這個(gè)臨時(shí)Actor會(huì)等待從接收ask消息的Actor返回的響應(yīng),其次,F(xiàn)uture也有額外的性能開(kāi)銷。
Ask會(huì)創(chuàng)建Future,由臨時(shí)Actor負(fù)責(zé)完成,這個(gè)開(kāi)銷并不大,但是如果需要非常高頻地執(zhí)行ask操作,那么還是要將這一開(kāi)銷考慮在內(nèi)的。
Ask很簡(jiǎn)單,不過(guò)考慮到性能,使用tell是更高效的解決方案。

1.3 Tell消息模式

epub_22651331_31.jpg

  • Tell是ActorRef/ActorSelection類的一個(gè)方法,它也可以接受一個(gè)響應(yīng)地址作為參數(shù),接收消息的Actor中的sender()其實(shí)就是這個(gè)響應(yīng)地址。
  • 在Scala中,默認(rèn)情況下,sender會(huì)被隱式定義為發(fā)送消息的Actor,如果沒(méi)有sender(如在Actor外部發(fā)起請(qǐng)求),那么響應(yīng)地址不會(huì)默認(rèn)設(shè)置為任何郵箱(叫做DeadLetters)。
1.4 Forward消息模式
  • Tell在語(yǔ)義上是用于將一條消息發(fā)送至另一個(gè)Actor,并將響應(yīng)地址設(shè)置為當(dāng)前的Actor。而Forward和郵件轉(zhuǎn)發(fā)非常類似:初始發(fā)送者保持不變,只不過(guò)新增了一個(gè)收件人。
  • 在使用tell時(shí),我們指定了一個(gè)響應(yīng)地址,或是將響應(yīng)地址隱式設(shè)為發(fā)送消息的Actor。而使用forward傳遞消息時(shí),響應(yīng)地址就是原始消息的發(fā)送者
  • 有時(shí)候我們需要將接受到的消息傳遞給另一個(gè)Actor來(lái)處理,而最終的處理結(jié)果需要傳回給初始發(fā)起請(qǐng)求的一方。

epub_22651331_34.jpg

  //Java
          actor.forward(result, getContext());

          //Scala
          actor forward message
1.4 Pipe消息模式

很多情況下,需要將Actor中的某個(gè)Future返回給請(qǐng)求發(fā)送者。上文介紹過(guò)sender()是一個(gè)方法,所以要在Future的回調(diào)函數(shù)中訪問(wèn)sender(),我們必須存儲(chǔ)一個(gè)指向sender()的引用:

  //Java
          final ActorRef senderRef = sender();
          future.map(x ->{senderRef.tell(x, ActorRef.noSender())});

          //Scala
          val senderRef = sender();
          future.map(x =>senderRef ! x);(原文為future.map(x =>senderRef ! ActorRef.noSender),有誤。)
  //Java
          pipe(future, system.dispatcher()).to(sender());

          //Scala
          future pipeTo sender()
          pipe(future) to sender()

pipe接受Future的結(jié)果作為參數(shù),然后將其傳遞給所提供的Actor引用。在上面的例子中,因?yàn)閟ender()執(zhí)行在當(dāng)前線程上,所以我們可以直接調(diào)用sender(),而不用干一些奇怪的事情(比如把sender()引用存儲(chǔ)在一個(gè)變量中),執(zhí)行結(jié)果一切正確。這就好多了!

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧


網(wǎng)站欄目:Akka學(xué)習(xí)(五)消息傳遞的方式-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://weahome.cn/article/dooois.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部