<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Shadow &#38; Honnix &#187; receive</title>
	<atom:link href="http://honnix.com/blog/archives/tag/receive/feed" rel="self" type="application/rss+xml" />
	<link>http://honnix.com/blog</link>
	<description>she&#039;s growing up</description>
	<lastBuildDate>Sun, 15 Jan 2012 10:44:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Scala的Actor机制简要分析</title>
		<link>http://honnix.com/blog/archives/392</link>
		<comments>http://honnix.com/blog/archives/392#comments</comments>
		<pubDate>Mon, 27 Jul 2009 15:49:35 +0000</pubDate>
		<dc:creator>honnix</dc:creator>
				<category><![CDATA[Scala]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Actor]]></category>
		<category><![CDATA[react]]></category>
		<category><![CDATA[receive]]></category>
		<category><![CDATA[Thread]]></category>
		<category><![CDATA[线程]]></category>

		<guid isPermaLink="false">http://honnix.com/blog/?p=392</guid>
		<description><![CDATA[Scala里多线程的基础就是Actor，核心思想是用消息传递来进行线程间的信息共享和同步。 Scala的Actor线程模型可以这样理解：所有Actor共享一个线程池，总的线程个数可以配置，也可以根据CPU个数决定；当一个Actor启动之后，Scala分配一个线程给它使用，如果使用receive模型，这个线程就一直为该Actor所有，如果使用react模型，Scala执行完react方法后抛出异常，则该线程就可以被其它Actor使用。 下面看一些核心代码。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def start&#40;&#41;: Actor = synchronized &#123; // Reset various flags. // // Note that we do *not* reset `trapExit`. The reason is that // users should be able to set the field in the&#8230;]]></description>
			<content:encoded><![CDATA[<p>Scala里多线程的基础就是Actor，核心思想是用消息传递来进行线程间的信息共享和同步。</p>
<p>Scala的Actor线程模型可以这样理解：所有Actor共享一个线程池，总的线程个数可以配置，也可以根据CPU个数决定；当一个Actor启动之后，Scala分配一个线程给它使用，如果使用receive模型，这个线程就一直为该Actor所有，如果使用react模型，Scala执行完react方法后抛出异常，则该线程就可以被其它Actor使用。</p>
<p><span id="more-392"></span></p>
<p>下面看一些核心代码。</p>

<div class="wp_codebox"><table><tr id="p3925"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code" id="p392code5"><pre class="scala" style="font-family:monospace;">  <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> start<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span> Actor <span style="color: #000080;">=</span> synchronized <span style="color: #F78811;">&#123;</span>
    <span style="color: #008000; font-style: italic;">// Reset various flags.</span>
    <span style="color: #008000; font-style: italic;">//</span>
    <span style="color: #008000; font-style: italic;">// Note that we do *not* reset `trapExit`. The reason is that</span>
    <span style="color: #008000; font-style: italic;">// users should be able to set the field in the constructor</span>
    <span style="color: #008000; font-style: italic;">// and before `act` is called.</span>
&nbsp;
    exitReason <span style="color: #000080;">=</span> <span style="color: #6666FF;">'normal
    exiting = false
    shouldExit = false
&nbsp;
    scheduler execute {
      ActorGC.newActor(Actor.this)
      (new Reaction(Actor.this)).run()
    }
&nbsp;
    this
  }</span></pre></td></tr></table></div>

<p>其中Reaction实现Runnable接口，scheduler基本相当于是一个线程池，所以调用start方法之后会有一个线程来为该Actor服务。</p>
<p>使用receive模型。</p>

<div class="wp_codebox"><table><tr id="p3926"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code" id="p392code6"><pre class="scala" style="font-family:monospace;">  <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> receive<span style="color: #F78811;">&#91;</span>R<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#40;</span>f<span style="color: #000080;">:</span> PartialFunction<span style="color: #F78811;">&#91;</span>Any, R<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span> R <span style="color: #000080;">=</span> <span style="color: #F78811;">&#123;</span>
    assert<span style="color: #F78811;">&#40;</span>Actor.<span style="color: #000000;">self</span> <span style="color: #000080;">==</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">this</span></a>, <span style="color: #6666FF;">&quot;receive from channel belonging to other actor&quot;</span><span style="color: #F78811;">&#41;</span>
    <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">this</span></a>.<span style="color: #000000;">synchronized</span> <span style="color: #F78811;">&#123;</span>
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span>shouldExit<span style="color: #F78811;">&#41;</span> exit<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">&#41;</span> <span style="color: #008000; font-style: italic;">// links</span>
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">val</span></a> qel <span style="color: #000080;">=</span> mailbox.<span style="color: #000000;">extractFirst</span><span style="color: #F78811;">&#40;</span><span style="color: #F78811;">&#40;</span>m<span style="color: #000080;">:</span> Any<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=&amp;</span>gt<span style="color: #000080;">;</span> f.<span style="color: #000000;">isDefinedAt</span><span style="color: #F78811;">&#40;</span>m<span style="color: #F78811;">&#41;</span><span style="color: #F78811;">&#41;</span>
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">null</span></a> eq qel<span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
        waitingFor <span style="color: #000080;">=</span> f.<span style="color: #000000;">isDefinedAt</span>
        isSuspended <span style="color: #000080;">=</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">true</span></a>
        suspendActor<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">&#41;</span>
      <span style="color: #F78811;">&#125;</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">else</span></a> <span style="color: #F78811;">&#123;</span>
        received <span style="color: #000080;">=</span> Some<span style="color: #F78811;">&#40;</span>qel.<span style="color: #000000;">msg</span><span style="color: #F78811;">&#41;</span>
        sessions <span style="color: #000080;">=</span> qel.<span style="color: #000000;">session</span> <span style="color: #000080;">::</span> sessions
      <span style="color: #F78811;">&#125;</span>
      waitingFor <span style="color: #000080;">=</span> waitingForNone
      isSuspended <span style="color: #000080;">=</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">false</span></a>
    <span style="color: #F78811;">&#125;</span>
    <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">val</span></a> result <span style="color: #000080;">=</span> f<span style="color: #F78811;">&#40;</span>received.<span style="color: #000000;">get</span><span style="color: #F78811;">&#41;</span>
    sessions <span style="color: #000080;">=</span> sessions.<span style="color: #000000;">tail</span>
    result
  <span style="color: #F78811;">&#125;</span></pre></td></tr></table></div>

<p>如果当前mailbox里面没有可以处理的消息，调用suspendActor，该方法会调用wait；如果有消息，这调用PartialFunction进行处理。</p>
<p>使用react模型。</p>

<div class="wp_codebox"><table><tr id="p3927"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code" id="p392code7"><pre class="scala" style="font-family:monospace;">  <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> react<span style="color: #F78811;">&#40;</span>f<span style="color: #000080;">:</span> PartialFunction<span style="color: #F78811;">&#91;</span>Any, Unit<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#41;</span><span style="color: #000080;">:</span> Nothing <span style="color: #000080;">=</span> <span style="color: #F78811;">&#123;</span>
    assert<span style="color: #F78811;">&#40;</span>Actor.<span style="color: #000000;">self</span> <span style="color: #000080;">==</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">this</span></a>, <span style="color: #6666FF;">&quot;react on channel belonging to other actor&quot;</span><span style="color: #F78811;">&#41;</span>
    <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">this</span></a>.<span style="color: #000000;">synchronized</span> <span style="color: #F78811;">&#123;</span>
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span>shouldExit<span style="color: #F78811;">&#41;</span> exit<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">&#41;</span> <span style="color: #008000; font-style: italic;">// links</span>
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">val</span></a> qel <span style="color: #000080;">=</span> mailbox.<span style="color: #000000;">extractFirst</span><span style="color: #F78811;">&#40;</span><span style="color: #F78811;">&#40;</span>m<span style="color: #000080;">:</span> Any<span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=&amp;</span>gt<span style="color: #000080;">;</span> f.<span style="color: #000000;">isDefinedAt</span><span style="color: #F78811;">&#40;</span>m<span style="color: #F78811;">&#41;</span><span style="color: #F78811;">&#41;</span>
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">null</span></a> eq qel<span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
        waitingFor <span style="color: #000080;">=</span> f.<span style="color: #000000;">isDefinedAt</span>
        continuation <span style="color: #000080;">=</span> f
        isDetached <span style="color: #000080;">=</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">true</span></a>
      <span style="color: #F78811;">&#125;</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">else</span></a> <span style="color: #F78811;">&#123;</span>
        sessions <span style="color: #000080;">=</span> List<span style="color: #F78811;">&#40;</span>qel.<span style="color: #000000;">session</span><span style="color: #F78811;">&#41;</span>
        scheduleActor<span style="color: #F78811;">&#40;</span>f, qel.<span style="color: #000000;">msg</span><span style="color: #F78811;">&#41;</span>
      <span style="color: #F78811;">&#125;</span>
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">throw</span></a> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">new</span></a> SuspendActorException
    <span style="color: #F78811;">&#125;</span>
  <span style="color: #F78811;">&#125;</span></pre></td></tr></table></div>

<p>如果当前mailbox没有可以处理的消息，设置waitingFor和continuation，这两个变量会在接收到消息的时候使用；如果有消息，则调用scheduleActor，该方法会在线程池里选择一个新的线程来处理，具体的处理方法也是由PartialFunction决定。不管是哪条路径，react都会立即返回，或者说是立即抛出异常，结束该线程的执行，这样该线程就可以被其它Actor使用。</p>
<p>再来看看接收消息的处理代码。</p>

<div class="wp_codebox"><table><tr id="p3928"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code" id="p392code8"><pre class="scala" style="font-family:monospace;">  <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">def</span></a> send<span style="color: #F78811;">&#40;</span>msg<span style="color: #000080;">:</span> Any, replyTo<span style="color: #000080;">:</span> OutputChannel<span style="color: #F78811;">&#91;</span>Any<span style="color: #F78811;">&#93;</span><span style="color: #F78811;">&#41;</span> <span style="color: #000080;">=</span> synchronized <span style="color: #F78811;">&#123;</span>
    <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span>waitingFor<span style="color: #F78811;">&#40;</span>msg<span style="color: #F78811;">&#41;</span><span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
      received <span style="color: #000080;">=</span> Some<span style="color: #F78811;">&#40;</span>msg<span style="color: #F78811;">&#41;</span>
&nbsp;
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span>isSuspended<span style="color: #F78811;">&#41;</span>
        sessions <span style="color: #000080;">=</span> replyTo <span style="color: #000080;">::</span> sessions
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">else</span></a>
        sessions <span style="color: #000080;">=</span> List<span style="color: #F78811;">&#40;</span>replyTo<span style="color: #F78811;">&#41;</span>
&nbsp;
      waitingFor <span style="color: #000080;">=</span> waitingForNone
&nbsp;
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span><span style="color: #000080;">!</span>onTimeout.<span style="color: #000000;">isEmpty</span><span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
        onTimeout.<span style="color: #000000;">get</span>.<span style="color: #000000;">cancel</span><span style="color: #F78811;">&#40;</span><span style="color: #F78811;">&#41;</span>
        onTimeout <span style="color: #000080;">=</span> None
      <span style="color: #F78811;">&#125;</span>
&nbsp;
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">if</span></a> <span style="color: #F78811;">&#40;</span>isSuspended<span style="color: #F78811;">&#41;</span>
        resumeActor<span style="color: #F78811;">&#40;</span><span style="color: #F78811;">&#41;</span>
      <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">else</span></a> <span style="color: #008000; font-style: italic;">// assert continuation != null</span>
        scheduler.<span style="color: #000000;">execute</span><span style="color: #F78811;">&#40;</span><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">new</span></a> Reaction<span style="color: #F78811;">&#40;</span><a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">this</span></a>, continuation, msg<span style="color: #F78811;">&#41;</span><span style="color: #F78811;">&#41;</span>
    <span style="color: #F78811;">&#125;</span> <a href="http://scala-lang.org"><span style="color: #0000ff; font-weight: bold;">else</span></a> <span style="color: #F78811;">&#123;</span>
      mailbox.<span style="color: #000000;">append</span><span style="color: #F78811;">&#40;</span>msg, replyTo<span style="color: #F78811;">&#41;</span>
    <span style="color: #F78811;">&#125;</span></pre></td></tr></table></div>

<p>}<br />
如果当前没有在等待消息或者接收到的消息不能处理，就丢到mailbox里去；相反，则进行消息的处理。这里对于receive模型和react模型就有了分支：如果isSuspended为true，表示是receive模型，并且线程在wait，就调用resumeActor，该方法会调用notify；否则就是react模型，同样在线程池里选择一个线程进行处理。</p>
]]></content:encoded>
			<wfw:commentRss>http://honnix.com/blog/archives/392/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

