﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-狂奔 lion</title><link>http://www.blogjava.net/yangyi/</link><description>自强不息</description><language>zh-cn</language><lastBuildDate>Tue, 28 Apr 2026 16:17:24 GMT</lastBuildDate><pubDate>Tue, 28 Apr 2026 16:17:24 GMT</pubDate><ttl>60</ttl><item><title>浅谈Java中的同步的方法和原理</title><link>http://www.blogjava.net/yangyi/archive/2010/07/09/325679.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 09 Jul 2010 11:49:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2010/07/09/325679.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/325679.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2010/07/09/325679.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/325679.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/325679.html</trackback:ping><description><![CDATA[<p><font style="background-color: #f2f2f2">Java的内存模型中Thread会附有自己的堆栈，寄存器，必要时需要和主存即heap之间同步。<br />
可以使用Synchornized关键字和Concurrent包中的Lock可以保证线程互斥和可见性。</font></p>
<p><font style="background-color: #f2f2f2">互斥性体现在类锁或者对象锁上，每个对象自身都包含一个监视器，该监视器是一个每次只能被一个线程所获取进入的临界区，可以通过wait和notify来退出和准入临界区。可以</font><font style="background-color: #f2f2f2">看出这是一个生产者-消费者的模型。而Concurrent包中的Lock为了能够获得更好的性能和更好的扩展性，以及不依赖于关键字的可读代码，自己实现了这样一个生产消费队列，也</font><font style="background-color: #f2f2f2">就是AbstractQueuedSynchronizer，被称为AQS的机制。每个Lock都内置了一个AbstractQueuedSynchronizer。需要说明的是AbstractQueuedSynchronizer内部实现采用了CAS机制</font><font style="background-color: #f2f2f2">，通过getState, setState, compareAndSetState访问控制一个32bit int的形式进行互斥。</font></p>
<p><font style="background-color: #f2f2f2">那么可见性是如何保证的呢？</font></p>
<p><font style="background-color: #f2f2f2">对于关键字的同步机制，其实可见性就是线程和主存之间的同步时机问题。共有4个时间点需要注意：<br />
1 获取或释放类锁/对象锁的时候。Thread保证reload/flush全部变更<br />
2 volatile就是flush on write或者reload on read<br />
3 当线程首次访问共享变量时，可以得到最新的结果。<br />
题外：所以在构造方法中公布this时很危险的。简单的说，就是构造时不逃脱任何变量，不开启新的线程，只做封装。关于安全构造，请参考<br />
http://www.ibm.com/developerworks/cn/java/j-jtp0618/#resources<br />
4 线程结束时，所有变更会写回主存</font></p>
<p><font style="background-color: #f2f2f2">关于Concurrent Lock如何实现可见性的问题，Doug Lea大侠，只在他的论文中提到，按照JSR133，Unsafe在getState, setState, compareAndSetState时保证了线程的变量的可见</font><font style="background-color: #f2f2f2">性，不需要额外的volatile支持，至于具体这些native做了哪些magic就不得而知了，总之，最后的contract就是保证lock区间的共享变量可见性。开发团队被逼急了就这样回答：<br />
<span style="color: #3366ff"><font style="background-color: #f2f2f2">There seems to be a real reluctance to explain the dirty details. I think the question was definitely understood on the concurrent interest thread, and the </font><font style="background-color: #f2f2f2">answer is that synchronized and concurrent locking are intended to be interchangable in terms of memory semantics when implemented correctly. The answer to </font><font style="background-color: #f2f2f2">matfud's question seems to be "trust us.&#8221;<br />
</font></span></font><font style="background-color: #f2f2f2"><br />
不过这个地方的确是开发团队给我们用户迷惑的地方，在同样应用了CAS机制的Atomic类中，都内嵌了volatile变量，但是再lock块中，他告诉我们可以保证可见性。</font></p>
<p><font style="background-color: #f2f2f2">感兴趣的同学可以下面的两个thread和Doug Lea的thesis：<br />
<a href="http://altair.cs.oswego.edu/pipermail/concurrency-interest/2005-June/001587.html">http://altair.cs.oswego.edu/pipermail/concurrency-interest/2005-June/001587.html</a><br />
<a href="http://forums.sun.com/thread.jspa?threadID=631014&amp;start=15&amp;tstart=0">http://forums.sun.com/thread.jspa?threadID=631014&amp;start=15&amp;tstart=0</a><br />
<a href="http://gee.cs.oswego.edu/dl/papers/aqs.pdf">http://gee.cs.oswego.edu/dl/papers/aqs.pdf</a><br />
</font></p>
<img src ="http://www.blogjava.net/yangyi/aggbug/325679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2010-07-09 19:49 <a href="http://www.blogjava.net/yangyi/archive/2010/07/09/325679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>commons-net FTPClient API存取设计</title><link>http://www.blogjava.net/yangyi/archive/2010/07/07/325504.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Wed, 07 Jul 2010 15:08:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2010/07/07/325504.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/325504.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2010/07/07/325504.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/325504.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/325504.html</trackback:ping><description><![CDATA[<sub>
<p>文件系统无非就是文件的存取和组织结构。<br />
访问一个文件系统的API也应该是写，读，定位方法（Pathname?/URI?）</p>
<p>FTPClient针对文件的保存和获取各提供了两个方法，分别是：<br />
</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; height: 87px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;storeFile(String&nbsp;remote,&nbsp;InputStream&nbsp;local)<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;OutputStream&nbsp;storeFileStream(String&nbsp;remote)<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /><br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;retrieveFile(String&nbsp;remote,&nbsp;OutputStream&nbsp;local)<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;InputStream&nbsp;retrieveFileStream(String&nbsp;remote)<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span></div>
<p>&nbsp;</p>
<p>两个方法貌似相同，实际不同，返回流的那个因为不能马上处理流，所以需要用户手工调用completePendingCommand，而另一个传递流进去的则不需要。可能有同学已经遇到过这个问题了，读写第一个文件时总是正确的，当相同API读写第二个文件时，block住了。这是因为FTPClient要求在进行流操作之后执行completePendingCommand，以确保流处理完毕，因为流处理不是即时的，所以也没有办法不手工调用completePendingCommand。问题是开发者把不返回流的方法末尾加上了completePendingCommand，如果不看代码可能根本不知道。<br />
文档上说：<br />
</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;There&nbsp;are&nbsp;a&nbsp;few&nbsp;FTPClient&nbsp;methods&nbsp;that&nbsp;</span><span style="color: #0000ff">do</span><span style="color: #000000">&nbsp;not&nbsp;complete&nbsp;the<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;entire&nbsp;sequence&nbsp;of&nbsp;FTP&nbsp;commands&nbsp;to&nbsp;complete&nbsp;a&nbsp;transaction.&nbsp;&nbsp;These<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;commands&nbsp;require&nbsp;some&nbsp;action&nbsp;by&nbsp;the&nbsp;programmer&nbsp;after&nbsp;the&nbsp;reception<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;of&nbsp;a&nbsp;positive&nbsp;intermediate&nbsp;command.&nbsp;&nbsp;After&nbsp;the&nbsp;programmer</span><span style="color: #000000">'</span><span style="color: #000000">s&nbsp;code</span><span style="color: #000000"><br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;completes&nbsp;its&nbsp;actions,&nbsp;it&nbsp;must&nbsp;call&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">&nbsp;method&nbsp;to&nbsp;receive<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;the&nbsp;completion&nbsp;reply&nbsp;from&nbsp;the&nbsp;server&nbsp;and&nbsp;verify&nbsp;the&nbsp;success&nbsp;of&nbsp;the<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;entire&nbsp;transaction.</span></div>
<p><br />
但是这样仍然还是让人有点困惑，为什么都是存储/读取的方法，有时候要调用completePendingCommand，有时候不调用？更严重的问题是completePendingCommand调用了getReply，如果一个命令通过socket stream传了过去但是没有getReply，即没有completePendingCommand，那么下次发命令时，将会受到本次返回码的干扰，得到无效的响应。而如果在completePendingCommand之后又进行了一次无辜的completePendingCommand，那么因为FTP Server上没有Reply了，就会block。所以completePendingCommand并不是可以随意添加的。</p>
<p>现在出现了两个问题：<br />
1 completePendingCommand很容易多出来或遗漏<br />
2 显式调用completePendingCommand暴露了底层实现，给用户带来不便，用户只想要InputStream或者OutputStream</p>
<p>为了解决这个问题，可以对InputStream进行扩展，建立一个ReplyOnCloseInputStream，如下：<br />
</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><img id="Codehighlighter1_58_285_Open_Image" onclick="this.style.display='none'; Codehighlighter1_58_285_Open_Text.style.display='none'; Codehighlighter1_58_285_Closed_Image.style.display='inline'; Codehighlighter1_58_285_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_58_285_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_58_285_Closed_Text.style.display='none'; Codehighlighter1_58_285_Open_Image.style.display='inline'; Codehighlighter1_58_285_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif"  alt="" /><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;ReplyOnCloseInputStream&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;InputStream</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_58_285_Closed_Text"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_58_285_Open_Text"><span style="color: #000000">{<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #008000"><br />
<img id="Codehighlighter1_129_143_Open_Image" onclick="this.style.display='none'; Codehighlighter1_129_143_Open_Text.style.display='none'; Codehighlighter1_129_143_Closed_Image.style.display='inline'; Codehighlighter1_129_143_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_129_143_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_129_143_Closed_Text.style.display='none'; Codehighlighter1_129_143_Open_Image.style.display='inline'; Codehighlighter1_129_143_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;ReplyOnCloseInputStream(InputStream&nbsp;is,&nbsp;FTPClient&nbsp;c)</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_129_143_Closed_Text"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_129_143_Open_Text"><span style="color: #000000">{<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #008000"><br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #008000"><br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;@override<br />
<img id="Codehighlighter1_186_283_Open_Image" onclick="this.style.display='none'; Codehighlighter1_186_283_Open_Text.style.display='none'; Codehighlighter1_186_283_Closed_Image.style.display='inline'; Codehighlighter1_186_283_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_186_283_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_186_283_Closed_Text.style.display='none'; Codehighlighter1_186_283_Open_Image.style.display='inline'; Codehighlighter1_186_283_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;close()</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_186_283_Closed_Text"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_186_283_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_220_244_Open_Image" onclick="this.style.display='none'; Codehighlighter1_220_244_Open_Text.style.display='none'; Codehighlighter1_220_244_Closed_Image.style.display='inline'; Codehighlighter1_220_244_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_220_244_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_220_244_Closed_Text.style.display='none'; Codehighlighter1_220_244_Open_Image.style.display='inline'; Codehighlighter1_220_244_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(c.completePendingCommand)</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_220_244_Closed_Text"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_220_244_Open_Text"><span style="color: #000000">{<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is.close();<br />
<img id="Codehighlighter1_249_279_Open_Image" onclick="this.style.display='none'; Codehighlighter1_249_279_Open_Text.style.display='none'; Codehighlighter1_249_279_Closed_Image.style.display='inline'; Codehighlighter1_249_279_Closed_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif"  alt="" /><img style="display: none" id="Codehighlighter1_249_279_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_249_279_Closed_Text.style.display='none'; Codehighlighter1_249_279_Open_Image.style.display='inline'; Codehighlighter1_249_279_Open_Text.style.display='inline';" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #0000ff">else</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_249_279_Closed_Text"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_249_279_Open_Text"><span style="color: #000000">{<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">throw&nbsp;Exception</span><span style="color: #008000"><br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif"  alt="" />&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif"  alt="" />}</span></span><span style="color: #000000">&nbsp;<br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #008000"><br />
<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ReplyOnCloseInputStream(is,&nbsp;client);</span></div>
<p><br />
这样封装之后，FTPClient的用户只需要正常在处理完流之后关闭即可，而不必暴露实现细节。保存文件也可以用相同的方法封装OutputStream。</p>
</sub>
<img src ="http://www.blogjava.net/yangyi/aggbug/325504.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2010-07-07 23:08 <a href="http://www.blogjava.net/yangyi/archive/2010/07/07/325504.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于ThreadLocal的内存泄露</title><link>http://www.blogjava.net/yangyi/archive/2010/07/02/325100.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 02 Jul 2010 10:27:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2010/07/02/325100.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/325100.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2010/07/02/325100.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/325100.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/325100.html</trackback:ping><description><![CDATA[ThreadLocal是一种confinement，confinement和local及immutable都是线程安全的（如果JVM可信的话）。因为对每个线程和value之间存在hash表，而线程数量未知，从表象来看ThreadLocal会存在内存泄露，读了代码，发现实际上也可能会内存泄露。<br />
<br />
事实上每个Thread实例都具备一个ThreadLocal的map，以ThreadLocal Instance为key，以绑定的Object为Value。而这个map不是普通的map，它是在ThreadLocal中定义的，它和普通map的最大区别就是它的Entry是针对ThreadLocal弱引用的，即当外部ThreadLocal引用为空时，map就可以把ThreadLocal交给GC回收，从而得到一个null的key。<br />
<br />
这个threadlocal内部的map在Thread实例内部维护了ThreadLocal Instance和bind value之间的关系，这个map有threshold，当超过threshold时，map会首先检查内部的ThreadLocal（前文说过，map是弱引用可以释放）是否为null，如果存在null，那么释放引用给gc，这样保留了位置给新的线程。如果不存在slate threadlocal，那么double threshold。除此之外，还有两个机会释放掉已经废弃的threadlocal占用的内存，一是当hash算法得到的table index刚好是一个null key的threadlocal时，直接用新的threadlocal替换掉已经废弃的。另外每次在map中新建一个entry时（即没有和用过的或未清理的entry命中时），会调用cleanSomeSlots来遍历清理空间。此外，当Thread本身销毁时，这个map也一定被销毁了（map在Thread之内），这样内部所有绑定到该线程的ThreadLocal的Object Value因为没有引用继续保持，所以被销毁。<br />
<br />
从上可以看出Java已经充分考虑了时间和空间的权衡，但是因为置为null的threadlocal对应的Object Value无法及时回收。map只有到达threshold时或添加entry时才做检查，不似gc是定时检查，不过我们可以手工轮询检查，显式调用map的remove方法，及时的清理废弃的threadlocal内存。需要说明的是，只要不往不用的threadlocal中放入大量数据，问题不大，毕竟还有回收的机制。<br />
<br />
综上，废弃threadlocal占用的内存会在3中情况下清理：<br />
1 thread结束，那么与之相关的threadlocal value会被清理<br />
2 GC后，thread.threadlocals(map) threshold超过最大值时，会清理<br />
3 GC后，thread.threadlocals(map) 添加新的Entry时，hash算法没有命中既有Entry时，会清理<br />
<br />
那么何时会&#8220;内存泄露&#8221;?当Thread长时间不结束，存在大量废弃的ThreadLocal，而又不再添加新的ThreadLocal（或新添加的ThreadLocal恰好和一个废弃ThreadLocal在map中命中）时。
<img src ="http://www.blogjava.net/yangyi/aggbug/325100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2010-07-02 18:27 <a href="http://www.blogjava.net/yangyi/archive/2010/07/02/325100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于软件文档，我的看法</title><link>http://www.blogjava.net/yangyi/archive/2010/06/29/324813.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Tue, 29 Jun 2010 10:26:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2010/06/29/324813.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/324813.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2010/06/29/324813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/324813.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/324813.html</trackback:ping><description><![CDATA[<font style="background-color: #f2f2f2">文档应该包括两大部分，一部分是清晰的代码结构和注释，比如Concurrent API就是这样，还有一部分是文字文档，包括三个小部分：一是开发文档，应该讲架构和功能；二是索引文档，详细介绍功能和参数，三是用户文档，包括安装和使用说明<br />
<br />
文档最困难的莫过于版本的一致性，当软件升级后，一些obsolete的内容和新的feature很难同步。要是架构发生了变化，那就更困难了。一般document team都不是太精于技术，所以也会产生一些问题。<br />
<br />
只能说任何事物永远都有改进的空间，但是同样也永远没有达到完美的程度</font>
<img src ="http://www.blogjava.net/yangyi/aggbug/324813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2010-06-29 18:26 <a href="http://www.blogjava.net/yangyi/archive/2010/06/29/324813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NIO学习之Web服务器示例</title><link>http://www.blogjava.net/yangyi/archive/2010/06/25/324501.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 25 Jun 2010 11:19:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2010/06/25/324501.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/324501.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2010/06/25/324501.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/324501.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/324501.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1 根据cpu core数量确定selector数量 2 用一个selector服务accept，其他selector按照core-1分配线程数运行 3 accept selector作为生产者把获得的请求放入队列 4 某个selector作为消费者从blocking queue中取出请求socket channel，并向自己注册 5 当获得read信号时，selector建立工作...&nbsp;&nbsp;<a href='http://www.blogjava.net/yangyi/archive/2010/06/25/324501.html'>阅读全文</a><img src ="http://www.blogjava.net/yangyi/aggbug/324501.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2010-06-25 19:19 <a href="http://www.blogjava.net/yangyi/archive/2010/06/25/324501.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程的知识</title><link>http://www.blogjava.net/yangyi/archive/2010/06/25/324500.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 25 Jun 2010 11:17:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2010/06/25/324500.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/324500.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2010/06/25/324500.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/324500.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/324500.html</trackback:ping><description><![CDATA[<strong>多线程的优点：</strong> <br />
1 多核利用 <br />
2 为单个任务建模方便 <br />
3 异步处理不同事件，不必盲等 <br />
4 现代的UI也需要它 <br />
<strong>风险：</strong> <br />
1 同步变量易错误 <br />
2 因资源限制导致线程活跃性问题 <br />
3 因2导致的性能问题 <br />
<strong>用途：</strong> <br />
框架，UI，Backend <br />
<strong>线程安全的本质是什么：</strong> <br />
并非是线程和锁，这些只是基础结构，本质是如何控制共享变量访问的状态 <br />
<strong>什么是线程安全：</strong> <br />
就是线程之间的执行<strong>还没有</strong>发生错误，就是没有发生意外 <br />
一个线程安全的类本身封装了对类内部方法和变量的异步请求，调用方无需考虑线程安全问题 <br />
无状态的变量总是线程安全的 <br />
<strong>原子性：</strong> <br />
完整执行的单元，如不加锁控制，则会发生竞态条件，如不加锁的懒汉单例模式，或者复合操作。 <br />
<strong>锁，内在锁，重入：</strong> <br />
利用synchronized关键字控制访问单元，同一线程可以重入锁内部，避免了面向对象产生的问题。同一变量的所有出现场合应该使用同一个锁来控制。synchronized(lock)。 <br />
即使所有方法都用synchronized控制也不能保证线程安全，它可能在调用时编程复合操作。 <br />
<strong>活跃性和性能问题：</strong> <br />
过大的粒度会导致这个问题，用锁进行异步控制，导致了线程的顺序执行。 <br />
简单和性能是一对矛盾，需要适当的取舍。不能在没有考虑成熟的情况下，为了性能去牺牲简洁性。 <br />
要尽量避免耗时操作，IO和网络操作中使用锁 
 <img src ="http://www.blogjava.net/yangyi/aggbug/324500.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2010-06-25 19:17 <a href="http://www.blogjava.net/yangyi/archive/2010/06/25/324500.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ext Store Filter的实现和问题</title><link>http://www.blogjava.net/yangyi/archive/2010/06/25/324499.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 25 Jun 2010 11:16:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2010/06/25/324499.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/324499.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2010/06/25/324499.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/324499.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/324499.html</trackback:ping><description><![CDATA[Store包含两个数据缓存 - snapshot和data，grid，combo等控件的显示全部基于data，而snapshot是数据的完整缓存，当首次应用过滤器时，snapshot从data中备份数据，当应用过滤器时，filter从snapshot获取一份完整的数据，并在其中进行过滤，过滤后的结果形成了data并传递给展示，及data总是过滤后的数据，而snapshot总是完整的数据，不过看名字让人误以为它们的作用正好相反。 <br />
相应地，当进行store的增删改时，要同时维护两个缓存。 <br />
<strong>问题</strong> <br />
Store包含两个增加Record的方法，即insert和add，其中的insert没有更新snapshot所以当重新应用filter时，即data被重新定义时，在data中使用insert新增的记录是无效的。 <br />
解决方法 <br />
用add不要用insert，如果用insert，记得把数据写进snapshot: store.snapshot.addAll(records) 
 <img src ="http://www.blogjava.net/yangyi/aggbug/324499.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2010-06-25 19:16 <a href="http://www.blogjava.net/yangyi/archive/2010/06/25/324499.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ext中Combo组件的联动封装</title><link>http://www.blogjava.net/yangyi/archive/2010/06/25/324498.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 25 Jun 2010 11:14:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2010/06/25/324498.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/324498.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2010/06/25/324498.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/324498.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/324498.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在Extjs中构造N级联动下拉的麻烦不少，需定制下拉数据并设定响应事件。通过对Combo集合的封装，无需自己配置Combo，只需设定数据和关联层级，即可自动构造出一组支持正向和逆向过滤的联动下拉并获取其中某一个的实例。 如： 数据： Ext.test&nbsp;=&nbsp;{};&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ext.test.lcbdata&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/yangyi/archive/2010/06/25/324498.html'>阅读全文</a><img src ="http://www.blogjava.net/yangyi/aggbug/324498.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2010-06-25 19:14 <a href="http://www.blogjava.net/yangyi/archive/2010/06/25/324498.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>前端框架动态组件和代码生成之间的选择</title><link>http://www.blogjava.net/yangyi/archive/2010/06/25/324497.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 25 Jun 2010 11:11:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2010/06/25/324497.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/324497.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2010/06/25/324497.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/324497.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/324497.html</trackback:ping><description><![CDATA[<div class="blog_content">目前主流的SSH开发架构中，为减轻开发者工作，便于管理开发过程，往往用到一些公共代码和组件，或者采用了基于模版的代码生成机制，对于后台的DAO，Service等因为架构决定，代码生成必不可少，但是在前端页面的实现上，却可以有两种不同的思路，一种是把配置信息直接封装成更高级别的组建，一种是进行代码生成。请大家讨论一下这两种方案的优劣，这里先抛砖引玉了。 <br />
<br />
相同点： <br />
配置信息：XML OR 数据库 <br />
<br />
控件化： <br />
优点： <br />
1 易于添加公共功能 <br />
2 修改配置数据直接生效 <br />
3 代码结构清晰，对开发者友好 <br />
缺点： <br />
1 重组内存中对象结构，性能没有代码生成好（但渲染时间相同） <br />
2 仅能控制组件自身封装的配置，不支持个性化修改，如果配置文件不支持的参数，则控件不支持 <br />
3 必须保证每个控件一个配置 <br />
<br />
代码生成： <br />
优点： <br />
1 性能较好 <br />
2 易于定制内容 <br />
3 可以只配置一个模版，然后做出多个简单的修改 <br />
缺点： <br />
1 不能针对多个页面同时添加公共功能 <br />
2 业务修改需要重新生成代码 <br />
3 开发者需要修改自动生成的代码，并需要了解一些底层的实现结构 <br />
<br />
=====================20091029 <br />
代码生成并不能提高工作效率，尤其是针对复杂的富客户端开发 <br />
开发组件可提提供一种有效的选项，但是在运行效率和内存处理上需要细心处理 </div>
<img src ="http://www.blogjava.net/yangyi/aggbug/324497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2010-06-25 19:11 <a href="http://www.blogjava.net/yangyi/archive/2010/06/25/324497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Javascript工作流引擎代码及实例</title><link>http://www.blogjava.net/yangyi/archive/2009/03/06/258280.html</link><dc:creator>杨一</dc:creator><author>杨一</author><pubDate>Fri, 06 Mar 2009 09:39:00 GMT</pubDate><guid>http://www.blogjava.net/yangyi/archive/2009/03/06/258280.html</guid><wfw:comment>http://www.blogjava.net/yangyi/comments/258280.html</wfw:comment><comments>http://www.blogjava.net/yangyi/archive/2009/03/06/258280.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/yangyi/comments/commentRss/258280.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yangyi/services/trackbacks/258280.html</trackback:ping><description><![CDATA[&nbsp;
<p><span style="font-family: 宋体">最近在学习</span>jBPM<span style="font-family: 宋体">和</span>Javascript<span style="font-family: 宋体">，所以按照一些相关概念自己写了下面的</span>200<span style="font-family: 宋体">行代码的&#8220;工作流引擎&#8221;，工作流管理系统包含了流程定义，引擎，及应用系统三个主要部分，下面的代码实现了流程的分支合并，目前只支持一种环节上的迁移。拷贝到</span>html<span style="font-family: 宋体">，双击就可以跑起来。</span></p>
<p><img height="354" alt="" src="http://www.blogjava.net/images/blogjava_net/yangyi/wf-instance.JPG" width="495" border="0" /></p>
<p>&nbsp;</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left-color: #cccccc; width: 98%; word-break: break-all; padding-top: 4px; background-color: #eeeeee; "><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;workflowDef&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start:{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fn:</span><span style="color: #000000">"</span><span style="color: #000000">begin</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">对应处理方法可以在内部定义，也可以在外部定义</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next:[</span><span style="color: #000000">"</span><span style="color: #000000">task1</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">task2</span><span style="color: #000000">"</span><span style="color: #000000">]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end:</span><span style="color: #000000">"</span><span style="color: #000000">end</span><span style="color: #000000">"</span><span style="color: #000000">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tasks:[{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:</span><span style="color: #000000">"</span><span style="color: #000000">task1</span><span style="color: #000000">"</span><span style="color: #000000">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fn:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务一</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务一前</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;after:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务一后</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next:[</span><span style="color: #000000">"</span><span style="color: #000000">task4</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">task5</span><span style="color: #000000">"</span><span style="color: #000000">]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:</span><span style="color: #000000">"</span><span style="color: #000000">task2</span><span style="color: #000000">"</span><span style="color: #000000">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fn:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务二</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务二前</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;after:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务二后</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next:[</span><span style="color: #000000">"</span><span style="color: #000000">task3</span><span style="color: #000000">"</span><span style="color: #000000">]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:</span><span style="color: #000000">"</span><span style="color: #000000">task3</span><span style="color: #000000">"</span><span style="color: #000000">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fn:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务三</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务三前</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; after:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务三后</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">定义合并的数量</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;merge:&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next:</span><span style="color: #000000">"</span><span style="color: #000000">EOWF</span><span style="color: #000000">"</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:</span><span style="color: #000000">"</span><span style="color: #000000">task4</span><span style="color: #000000">"</span><span style="color: #000000">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fn:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务四</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务四前</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;after:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务四后</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next:[</span><span style="color: #000000">"</span><span style="color: #000000">task3</span><span style="color: #000000">"</span><span style="color: #000000">]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id:</span><span style="color: #000000">"</span><span style="color: #000000">task5</span><span style="color: #000000">"</span><span style="color: #000000">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fn:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务五</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务五前</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;after:</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">执行任务五后</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next:[</span><span style="color: #000000">"</span><span style="color: #000000">task3</span><span style="color: #000000">"</span><span style="color: #000000">]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}]<br />
}<br />
</span></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left-color: #cccccc; width: 98%; word-break: break-all; padding-top: 4px; background-color: #eeeeee; "><span style="color: #008000">//</span><span style="color: #008000">////////定义引擎////////////</span><span style="color: #008000"><br />
</span><span style="color: #000000"><br />
Yi&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;{};<br />
Yi.Utils&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;{};<br />
Yi.Utils.execute&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">function</span><span style="color: #000000">(o){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(</span><span style="color: #0000ff">typeof</span><span style="color: #000000">&nbsp;o&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;'</span><span style="color: #0000ff">function</span><span style="color: #000000">')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eval(o)();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o();<br />
}<br />
</span><span style="color: #008000">//</span><span style="color: #008000">工作流类</span><span style="color: #000000"><br />
Yi.Workflow&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">function</span><span style="color: #000000">(workflowDef){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.def&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;workflowDef;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.tasks&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.def.tasks;<br />
}<br />
</span><span style="color: #008000">//</span><span style="color: #008000">public按照环节id查找查找</span><span style="color: #000000"><br />
Yi.Workflow.prototype.findTask&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">function</span><span style="color: #000000">(taskId){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">(</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;i</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">this</span><span style="color: #000000">.tasks.length;i</span><span style="color: #000000">++</span><span style="color: #000000">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(</span><span style="color: #0000ff">this</span><span style="color: #000000">.tasks[i].id&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;taskId)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.tasks[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span><span style="color: #008000">//</span><span style="color: #008000">public启动工作流</span><span style="color: #000000"><br />
Yi.Workflow.prototype.start&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;[];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Yi.Utils.execute(</span><span style="color: #0000ff">this</span><span style="color: #000000">.def.start.fn);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">(</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;i</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">this</span><span style="color: #000000">.def.start.next.length;i</span><span style="color: #000000">++</span><span style="color: #000000">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.findTask(</span><span style="color: #0000ff">this</span><span style="color: #000000">.def.start.next[i]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Yi.Utils.execute(</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks[i].before);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span><span style="color: #008000">//</span><span style="color: #008000">private</span><span style="color: #000000"><br />
Yi.Workflow.prototype.findCurrentTaskById&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">function</span><span style="color: #000000">(taskId){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">(</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;i</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks.length;i</span><span style="color: #000000">++</span><span style="color: #000000">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks[i].id&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;taskId)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
}<br />
</span><span style="color: #008000">//</span><span style="color: #008000">private</span><span style="color: #000000"><br />
Yi.Workflow.prototype.removeFromCurrentTasks&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">function</span><span style="color: #000000">(task){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;temp&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;[];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">(</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;i</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks.length;i</span><span style="color: #000000">++</span><span style="color: #000000">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(</span><span style="color: #000000">!</span><span style="color: #000000">(</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks[i]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;task))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp.push(</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks[i]);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
}<br />
</span><span style="color: #008000">//</span><span style="color: #008000">public触发当前环节</span><span style="color: #000000"><br />
Yi.Workflow.prototype.signal&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">function</span><span style="color: #000000">(taskId){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">只处理当前活动环节</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;task&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.findCurrentTaskById(taskId);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(task&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">工作流未流转到此环节!</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">对于合并的处理</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(task.merge&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;undefined){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(task.merge&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">工作流流转条件不充分!</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff">else</span><span style="color: #000000">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Yi.Utils.execute(task.before);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">触发当前环节</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Yi.Utils.execute(task.fn);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">触发后动作</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Yi.Utils.execute(task.after);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">下一步如果工作流结束</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(task.next&nbsp;</span><span style="color: #000000">===</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">EOWF</span><span style="color: #000000">"</span><span style="color: #000000">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Yi.Utils.execute(</span><span style="color: #0000ff">this</span><span style="color: #000000">.def.end);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">delete</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">遍历下一步环节</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.removeFromCurrentTasks(task);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">(</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;i</span><span style="color: #000000">&lt;</span><span style="color: #000000">task.next.length;i</span><span style="color: #000000">++</span><span style="color: #000000">){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;tempTask&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.findTask(task.next[i]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(</span><span style="color: #000000">!</span><span style="color: #000000">tempTask.inCurrentTasks)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks.push(tempTask);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(tempTask.merge&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;undefined){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempTask.merge</span><span style="color: #000000">--</span><span style="color: #000000">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempTask.inCurrentTasks&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Yi.Utils.execute(tempTask.before);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span><span style="color: #008000">//</span><span style="color: #008000">public获取当前的活动环节</span><span style="color: #000000"><br />
Yi.Workflow.prototype.getCurrentTasks&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.currentTasks;<br />
}<br />
</span><span style="color: #008000">//</span><span style="color: #008000">public获取流程定义</span><span style="color: #000000"><br />
Yi.Workflow.prototype.getDef&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">function</span><span style="color: #000000">(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.def;<br />
}</span></div>
<p>&nbsp;</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left-color: #cccccc; width: 98%; word-break: break-all; padding-top: 4px; background-color: #eeeeee; "><span style="color: #008000">//</span><span style="color: #008000">//////应用系统///////////////</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">var</span><span style="color: #000000">&nbsp;wf&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Yi.Workflow(workflowDef);<br />
alert(</span><span style="color: #000000">"</span><span style="color: #000000">启动工作流</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
wf.start();<br />
alert(</span><span style="color: #000000">"</span><span style="color: #000000">尝试手工执行任务3,返回工作流没有流转到这里</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
wf.signal(</span><span style="color: #000000">"</span><span style="color: #000000">task3</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
alert(</span><span style="color: #000000">"</span><span style="color: #000000">分支开始</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
alert(</span><span style="color: #000000">"</span><span style="color: #000000">手工执行任务1</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
wf.signal(</span><span style="color: #000000">"</span><span style="color: #000000">task1</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
alert(</span><span style="color: #000000">"</span><span style="color: #000000">手工执行任务2</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
wf.signal(</span><span style="color: #000000">"</span><span style="color: #000000">task2</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
alert(</span><span style="color: #000000">"</span><span style="color: #000000">手工执行任务4</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
wf.signal(</span><span style="color: #000000">"</span><span style="color: #000000">task4</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
alert(</span><span style="color: #000000">"</span><span style="color: #000000">手工执行任务5</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
wf.signal(</span><span style="color: #000000">"</span><span style="color: #000000">task5</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
alert(</span><span style="color: #000000">"</span><span style="color: #000000">手工执行任务3</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
wf.signal(</span><span style="color: #000000">"</span><span style="color: #000000">task3</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #0000ff">function</span><span style="color: #000000">&nbsp;begin(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">流程开始，该函数在外部定义</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
}<br />
</span><span style="color: #0000ff">function</span><span style="color: #000000">&nbsp;end(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="color: #000000">"</span><span style="color: #000000">流程结束</span><span style="color: #000000">"</span><span style="color: #000000; ">);<br />
}<br />
</span></div>
<img src ="http://www.blogjava.net/yangyi/aggbug/258280.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yangyi/" target="_blank">杨一</a> 2009-03-06 17:39 <a href="http://www.blogjava.net/yangyi/archive/2009/03/06/258280.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>