??xml version="1.0" encoding="utf-8" standalone="yes"?>97成人超碰免,久久一区二区三区喷水,久久9999免费视频http://www.aygfsteel.com/yangyi/自强不息zh-cnSun, 18 May 2025 03:52:07 GMTSun, 18 May 2025 03:52:07 GMT60谈Java中的同步的方法和原理http://www.aygfsteel.com/yangyi/archive/2010/07/09/325679.html杨一杨一Fri, 09 Jul 2010 11:49:00 GMThttp://www.aygfsteel.com/yangyi/archive/2010/07/09/325679.htmlhttp://www.aygfsteel.com/yangyi/comments/325679.htmlhttp://www.aygfsteel.com/yangyi/archive/2010/07/09/325679.html#Feedback0http://www.aygfsteel.com/yangyi/comments/commentRss/325679.htmlhttp://www.aygfsteel.com/yangyi/services/trackbacks/325679.htmlJava的内存模型中Thread会附有自q堆栈Q寄存器Q必要时需要和d即heap之间同步?br /> 可以使用Synchornized关键字和Concurrent包中的Lock可以保证U程互斥和可见性?/font>

互斥性体现在c锁或者对象锁上,每个对象自n都包含一个监视器Q该监视器是一个每ơ只能被一个线E所获取q入的界区Q可以通过wait和notify来退出和准入临界区。可?/font>看出q是一个生产?消费者的模型。而Concurrent包中的LockZ能够获得更好的性能和更好的扩展性,以及不依赖于关键字的可读代码Q自己实Cq样一个生产消贚w列,?/font>是AbstractQueuedSynchronizerQ被UCؓAQS的机制。每个Lock都内|了一个AbstractQueuedSynchronizer。需要说明的是AbstractQueuedSynchronizer内部实现采用了CAS机制Q通过getState, setState, compareAndSetState讉K控制一?2bit int的Ş式进行互斥?/font>

那么可见性是如何保证的呢Q?/font>

对于关键字的同步机制Q其实可见性就是线E和d之间的同步时机问题。共?个时间点需要注意:
1 获取或释攄?对象锁的时候。Thread保证reload/flush全部变更
2 volatile是flush on write或者reload on read
3 当线E首ơ访问共享变量时Q可以得到最新的l果?br /> 题外Q所以在构造方法中公布this时很危险的。简单的_是构造时不逃脱M变量Q不开启新的线E,只做装。关于安全构造,请参?br /> http://www.ibm.com/developerworks/cn/java/j-jtp0618/#resources
4 U程l束Ӟ所有变更会写回d

关于Concurrent Lock如何实现可见性的问题QDoug Lea大侠Q只在他的论文中提到Q按照JSR133QUnsafe在getState, setState, compareAndSetState时保证了U程的变量的可见性,不需要额外的volatile支持Q至于具体这些native做了哪些magic׃得而知了,MQ最后的contract是保证lock区间的共享变量可见性。开发团队被逼急了p样回{:
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 answer is that synchronized and concurrent locking are intended to be interchangable in terms of memory semantics when implemented correctly. The answer to matfud's question seems to be "trust us.”

不过q个地方的确是开发团队给我们用户qh的地方,在同样应用了CAS机制的AtomiccMQ都内嵌了volatile变量Q但是再lock块中Q他告诉我们可以保证可见性?/font>

感兴的同学可以下面的两个thread和Doug Lea的thesisQ?br /> http://altair.cs.oswego.edu/pipermail/concurrency-interest/2005-June/001587.html
http://forums.sun.com/thread.jspa?threadID=631014&start=15&tstart=0
http://gee.cs.oswego.edu/dl/papers/aqs.pdf



杨一 2010-07-09 19:49 发表评论
]]>
commons-net FTPClient API存取设计http://www.aygfsteel.com/yangyi/archive/2010/07/07/325504.html杨一杨一Wed, 07 Jul 2010 15:08:00 GMThttp://www.aygfsteel.com/yangyi/archive/2010/07/07/325504.htmlhttp://www.aygfsteel.com/yangyi/comments/325504.htmlhttp://www.aygfsteel.com/yangyi/archive/2010/07/07/325504.html#Feedback1http://www.aygfsteel.com/yangyi/comments/commentRss/325504.htmlhttp://www.aygfsteel.com/yangyi/services/trackbacks/325504.html

文gpȝ无非是文g的存取和l织l构?br /> 讉K一个文件系l的API也应该是写,读,定位ҎQPathname?/URI?Q?/p>

FTPClient针对文g的保存和获取各提供了两个ҎQ分别是Q?br />

public boolean storeFile(String remote, InputStream local)
public OutputStream storeFileStream(String remote)

public boolean retrieveFile(String remote, OutputStream local)
public InputStream retrieveFileStream(String remote)

 

两个Ҏ貌似相同Q实际不同,q回的那个因ؓ不能马上处理,所以需要用h工调用completePendingCommandQ而另一个传递流q去的则不需要。可能有同学已经遇到q这个问题了Q读写第一个文件时L正确的,当相同APIdW二个文件时Qblock住了。这是因为FTPClient要求在进行流操作之后执行completePendingCommandQ以保处理完毕,因ؓ处理不是即时的Q所以也没有办法不手工调用completePendingCommand。问题是开发者把不返回流的方法末֊上了completePendingCommandQ如果不看代码可能根本不知道?br /> 文上说Q?br />

     * There are a few FTPClient methods that do not complete the
     
* entire sequence of FTP commands to complete a transaction.  These
     
* commands require some action by the programmer after the reception
     
* of a positive intermediate command.  After the programmer's code
     * completes its actions, it must call this method to receive
     
* the completion reply from the server and verify the success of the
     
* entire transaction.


但是q样仍然q是让h有点困惑Qؓ什么都是存?d的方法,有时候要调用completePendingCommandQ有时候不调用Q更严重的问题是completePendingCommand调用了getReplyQ如果一个命令通过socket stream传了q去但是没有getReplyQ即没有completePendingCommandQ那么下ơ发命oӞ会受到本次q回码的q扰Q得到无效的响应。而如果在completePendingCommand之后又进行了一ơ无辜的completePendingCommandQ那么因为FTP Server上没有Reply了,׃block。所以completePendingCommandq不是可以随意添加的?/p>

现在出现了两个问题:
1 completePendingCommand很容易多出来或遗?br /> 2 昑ּ调用completePendingCommand暴露了底层实玎ͼl用户带来不便,用户只想要InputStream或者OutputStream

Z解决q个问题Q可以对InputStreamq行扩展Q徏立一个ReplyOnCloseInputStreamQ如下:

private static ReplyOnCloseInputStream extends InputStream{
  
//
  public ReplyOnCloseInputStream(InputStream is, FTPClient c){
    
//
  }

  
//
  @override
  
public void close(){
    
if(c.completePendingCommand){
      is.close();
    }
else{
      
//throw Exception
    }

  }

}
 
//
return new ReplyOnCloseInputStream(is, client);


q样装之后QFTPClient的用户只需要正常在处理完流之后关闭卛_Q而不必暴露实现细节。保存文件也可以用相同的Ҏ装OutputStream?/p>

杨一 2010-07-07 23:08 发表评论
]]>
关于ThreadLocal的内存泄?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/yangyi/archive/2010/07/02/325100.html</guid><wfw:comment>http://www.aygfsteel.com/yangyi/comments/325100.html</wfw:comment><comments>http://www.aygfsteel.com/yangyi/archive/2010/07/02/325100.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yangyi/comments/commentRss/325100.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yangyi/services/trackbacks/325100.html</trackback:ping><description><![CDATA[ThreadLocal是一UconfinementQconfinement和local及immutable都是U程安全的(如果JVM可信的话Q。因为对每个U程和value之间存在hash表,而线E数量未知,从表象来看ThreadLocal会存在内存泄ԌM代码Q发现实际上也可能会内存泄露?br /> <br /> 事实上每个Thread实例都具备一个ThreadLocal的mapQ以ThreadLocal Instance为keyQ以l定的Object为Value。而这个map不是普通的mapQ它是在ThreadLocal中定义的Q它和普通map的最大区别就是它的Entry是针对ThreadLocal弱引用的Q即当外部ThreadLocal引用为空Ӟmap可以把ThreadLocal交给GC回收Q从而得C个null的key?br /> <br /> q个threadlocal内部的map在Thread实例内部l护了ThreadLocal Instance和bind value之间的关p,q个map有thresholdQ当过thresholdӞmap会首先检查内部的ThreadLocalQ前文说q,map是弱引用可以释放Q是否ؓnullQ如果存在nullQ那么释攑ּ用给gcQ这样保留了位置l新的线E。如果不存在slate threadlocalQ那么double threshold。除此之外,q有两个Z释放掉已l废弃的threadlocal占用的内存,一是当hash法得到的table index刚好是一个null key的threadlocalӞ直接用新的threadlocal替换掉已l废弃的。另外每ơ在map中新Z个entryӞx有和用过的或未清理的entry命中ӞQ会调用cleanSomeSlots来遍历清理空间。此外,当Thread本n销毁时Q这个map也一定被销毁了Qmap在Thread之内Q,q样内部所有绑定到该线E的ThreadLocal的Object Value因ؓ没有引用l箋保持Q所以被销毁?br /> <br /> 从上可以看出Java已经充分考虑了时间和I间的权衡,但是因ؓ|ؓnull的threadlocal对应的Object Value无法及时回收。map只有到达threshold时或dentry时才做检查,不似gc是定时检查,不过我们可以手工轮询查,昑ּ调用map的removeҎQ及时的清理废弃的threadlocal内存。需要说明的是,只要不往不用的threadlocal中放入大量数据,问题不大Q毕竟还有回收的机制?br /> <br /> lgQ废弃threadlocal占用的内存会?中情况下清理Q?br /> 1 threadl束Q那么与之相关的threadlocal value会被清理<br /> 2 GC后,thread.threadlocals(map) threshold过最大值时Q会清理<br /> 3 GC后,thread.threadlocals(map) d新的EntryӞhash法没有命中既有EntryӞ会清?br /> <br /> 那么何时?#8220;内存泄露”?当Thread长时间不l束Q存在大量废弃的ThreadLocalQ而又不再d新的ThreadLocalQ或新添加的ThreadLocal恰好和一个废弃ThreadLocal在map中命中)时? <img src ="http://www.aygfsteel.com/yangyi/aggbug/325100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yangyi/" target="_blank">杨一</a> 2010-07-02 18:27 <a href="http://www.aygfsteel.com/yangyi/archive/2010/07/02/325100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于软g文Q我的看?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/yangyi/archive/2010/06/29/324813.html</guid><wfw:comment>http://www.aygfsteel.com/yangyi/comments/324813.html</wfw:comment><comments>http://www.aygfsteel.com/yangyi/archive/2010/06/29/324813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yangyi/comments/commentRss/324813.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yangyi/services/trackbacks/324813.html</trackback:ping><description><![CDATA[<font style="background-color: #f2f2f2">文档应该包括两大部分Q一部分是清晰的代码l构和注释,比如Concurrent API是q样Q还有一部分是文字文,包括三个部分:一是开发文,应该讲架构和功能Q二是烦引文,详细介绍功能和参敎ͼ三是用户文Q包括安装和使用说明<br /> <br /> 文档最困难的莫q于版本的一致性,当Y件升U后Q一些obsolete的内容和新的feature很难同步。要是架构发生了变化Q那更困难了。一般document team都不是太_于技术,所以也会生一些问题?br /> <br /> 只能说Q何事物永q都有改q的I间Q但是同样也永远没有辑ֈ完美的程?/font> <img src ="http://www.aygfsteel.com/yangyi/aggbug/324813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yangyi/" target="_blank">杨一</a> 2010-06-29 18:26 <a href="http://www.aygfsteel.com/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.aygfsteel.com/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.aygfsteel.com/yangyi/archive/2010/06/25/324501.html</guid><wfw:comment>http://www.aygfsteel.com/yangyi/comments/324501.html</wfw:comment><comments>http://www.aygfsteel.com/yangyi/archive/2010/06/25/324501.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yangyi/comments/commentRss/324501.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yangyi/services/trackbacks/324501.html</trackback:ping><description><![CDATA[     摘要: 1 Ҏcpu core数量定selector数量 2 用一个selector服务acceptQ其他selector按照core-1分配U程数运? 3 accept selector作ؓ生者把获得的请求放入队? 4 某个selector作ؓ消费者从blocking queue中取求socket channelQƈ向自己注? 5 当获得read信号Ӟselector建立工作...  <a href='http://www.aygfsteel.com/yangyi/archive/2010/06/25/324501.html'>阅读全文</a><img src ="http://www.aygfsteel.com/yangyi/aggbug/324501.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yangyi/" target="_blank">杨一</a> 2010-06-25 19:19 <a href="http://www.aygfsteel.com/yangyi/archive/2010/06/25/324501.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线E的知识http://www.aygfsteel.com/yangyi/archive/2010/06/25/324500.html杨一杨一Fri, 25 Jun 2010 11:17:00 GMThttp://www.aygfsteel.com/yangyi/archive/2010/06/25/324500.htmlhttp://www.aygfsteel.com/yangyi/comments/324500.htmlhttp://www.aygfsteel.com/yangyi/archive/2010/06/25/324500.html#Feedback0http://www.aygfsteel.com/yangyi/comments/commentRss/324500.htmlhttp://www.aygfsteel.com/yangyi/services/trackbacks/324500.html多线E的优点Q?/strong>
1 多核利用
2 为单个Q务徏模方?
3 异步处理不同事gQ不必盲{?
4 C的UI也需要它
风险Q?/strong>
1 同步变量易错?
2 因资源限制导致线E活跃性问?
3 ?D的性能问题
用途:
框架QUIQBackend
U程安全的本质是什么:
q是线E和锁,q些只是基础l构Q本质是如何控制׃n变量讉K的状?
什么是U程安全Q?/strong>
是U程之间的执?strong>q没?/strong>发生错误Q就是没有发生意?
一个线E安全的cLw封装了对类内部Ҏ和变量的异步hQ调用方无需考虑U程安全问题
无状态的变量LU程安全?
原子性:
完整执行的单元,如不加锁控制Q则会发生竞态条Ӟ如不加锁的懒汉单例模式,或者复合操作?
锁,内在锁,重入Q?/strong>
利用synchronized关键字控制访问单元,同一U程可以重入锁内部,避免了面向对象生的问题。同一变量的所有出现场合应该用同一个锁来控制。synchronized(lock)?
即所有方法都用synchronized控制也不能保证线E安全,它可能在调用时编E复合操作?
z跃性和性能问题Q?/strong>
q大的粒度会Dq个问题Q用锁进行异步控ӞD了线E的序执行?
单和性能是一对矛盾,需要适当的取舍。不能在没有考虑成熟的情况下Qؓ了性能ȝ牲简z性?
要尽量避免耗时操作QIO和网l操作中使用?

杨一 2010-06-25 19:17 发表评论
]]>
Ext Store Filter的实现和问题http://www.aygfsteel.com/yangyi/archive/2010/06/25/324499.html杨一杨一Fri, 25 Jun 2010 11:16:00 GMThttp://www.aygfsteel.com/yangyi/archive/2010/06/25/324499.htmlhttp://www.aygfsteel.com/yangyi/comments/324499.htmlhttp://www.aygfsteel.com/yangyi/archive/2010/06/25/324499.html#Feedback0http://www.aygfsteel.com/yangyi/comments/commentRss/324499.htmlhttp://www.aygfsteel.com/yangyi/services/trackbacks/324499.html 相应圎ͼ当进行store的增删改Ӟ要同时维护两个缓存?
问题
Store包含两个增加Record的方法,即insert和addQ其中的insert没有更新snapshot所以当重新应用filterӞ即data被重新定义时Q在data中用insert新增的记录是无效的?
解决Ҏ
用add不要用insertQ如果用insertQ记得把数据写进snapshot: store.snapshot.addAll(records)

杨一 2010-06-25 19:16 发表评论
]]>
Ext中Combolg的联动封?/title><link>http://www.aygfsteel.com/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.aygfsteel.com/yangyi/archive/2010/06/25/324498.html</guid><wfw:comment>http://www.aygfsteel.com/yangyi/comments/324498.html</wfw:comment><comments>http://www.aygfsteel.com/yangyi/archive/2010/06/25/324498.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/yangyi/comments/commentRss/324498.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/yangyi/services/trackbacks/324498.html</trackback:ping><description><![CDATA[     摘要: 在Extjs中构造NU联动下拉的ȝ不少Q需定制下拉数据q设定响应事件。通过对Combo集合的封装,无需自己配置ComboQ只需讑֮数据和关联层U,卛_自动构造出一l支持正向和逆向qo的联动下拉ƈ获取其中某一个的实例? 如: 数据Q? Ext.test = {};       Ext.test.lcbdata&nb...  <a href='http://www.aygfsteel.com/yangyi/archive/2010/06/25/324498.html'>阅读全文</a><img src ="http://www.aygfsteel.com/yangyi/aggbug/324498.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yangyi/" target="_blank">杨一</a> 2010-06-25 19:14 <a href="http://www.aygfsteel.com/yangyi/archive/2010/06/25/324498.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>前端框架动态组件和代码生成之间的选择http://www.aygfsteel.com/yangyi/archive/2010/06/25/324497.html杨一杨一Fri, 25 Jun 2010 11:11:00 GMThttp://www.aygfsteel.com/yangyi/archive/2010/06/25/324497.htmlhttp://www.aygfsteel.com/yangyi/comments/324497.htmlhttp://www.aygfsteel.com/yangyi/archive/2010/06/25/324497.html#Feedback0http://www.aygfsteel.com/yangyi/comments/commentRss/324497.htmlhttp://www.aygfsteel.com/yangyi/services/trackbacks/324497.html目前L的SSH开发架构中Qؓ减轻开发者工作,便于理开发过E,往往用到一些公׃码和lgQ或者采用了Z模版的代码生成机Ӟ对于后台的DAOQService{因为架构决定,代码生成必不可少Q但是在前端面的实CQ却可以有两U不同的思\Q一U是把配|信息直接封装成更高U别的组建,一U是q行代码生成。请大家讨论一下这两种Ҏ的优劣,q里先抛砖引玉了?

相同点:
配置信息QXML OR 数据?

控g化:
优点Q?
1 易于d公共功能
2 修改配置数据直接生效
3 代码l构清晰Q对开发者友?
~点Q?
1 重组内存中对象结构,性能没有代码生成好(但渲染时间相同)
2 仅能控制lg自n装的配|,不支持个性化修改Q如果配|文件不支持的参敎ͼ则控件不支持
3 必须保证每个控g一个配|?

代码生成Q?
优点Q?
1 性能较好
2 易于定制内容
3 可以只配|一个模版,然后做出多个单的修改
~点Q?
1 不能针对多个面同时d公共功能
2 业务修改需要重新生成代?
3 开发者需要修改自动生成的代码Qƈ需要了解一些底层的实现l构

=====================20091029
代码生成q不能提高工作效率,其是针对复杂的富客L开?
开发组件可提提供一U有效的选项Q但是在q行效率和内存处理上需要细心处?

杨一 2010-06-25 19:11 发表评论
]]>
Javascript工作引擎代码及实例http://www.aygfsteel.com/yangyi/archive/2009/03/06/258280.html杨一杨一Fri, 06 Mar 2009 09:39:00 GMThttp://www.aygfsteel.com/yangyi/archive/2009/03/06/258280.htmlhttp://www.aygfsteel.com/yangyi/comments/258280.htmlhttp://www.aygfsteel.com/yangyi/archive/2009/03/06/258280.html#Feedback1http://www.aygfsteel.com/yangyi/comments/commentRss/258280.htmlhttp://www.aygfsteel.com/yangyi/services/trackbacks/258280.html最q在学习jBPM?/span>JavascriptQ所以按照一些相x念自己写了下面的200行代码的“工作引?#8221;Q工作流理pȝ包含了流E定义,引擎Q及应用pȝ三个主要部分Q下面的代码实现了流E的分支合ƈQ目前只支持一U环节上的迁UR拷贝到htmlQ双d可以跑v来?/span>

 

var workflowDef = {
         start:{
                   fn:
"begin"//对应处理Ҏ可以在内部定义,也可以在外部定义
                   next:[
"task1","task2"]
         },
         end:
"end",
         tasks:[{
                   id:
"task1",
                   fn:
function(){
                            alert(
"执行d一");
                   },
                   before:
function(){
                            alert(
"执行d一?/span>");
                   },
                   after:
function(){
                            alert(
"执行d一?/span>");
                   },
                   next:[
"task4","task5"]
         },{
                   id:
"task2",
                   fn:
function(){
                            alert(
"执行d?/span>");
                   },
                   before:
function(){
                            alert(
"执行d二前");
                   },
                   after:
function(){
                            alert(
"执行d二后");
                   },
                   next:[
"task3"]
         },{
                   id:
"task3",
                   fn:
function(){
                            alert(
"执行d?/span>");
                   },
                   before:
function(){
                            alert(
"执行d三前");
                   },
                   after:
function(){
                            alert(
"执行d三后");
                   },
                   
//定义合ƈ的数?/span>
                   merge: 
3,
                   next:
"EOWF"
         },{
                   id:
"task4",
                   fn:
function(){
                            alert(
"执行d?/span>");
                   },
                   before:
function(){
                            alert(
"执行d四前");
                   },
                   after:
function(){
                            alert(
"执行d四后");
                   },
                   next:[
"task3"]
         },{
                   id:
"task5",
                   fn:
function(){
                            alert(
"执行d?/span>");
                   },
                   before:
function(){
                            alert(
"执行d五前");
                   },
                   after:
function(){
                            alert(
"执行d五后");
                   },
                   next:[
"task3"]
         }]
}

 

 

//////////定义引擎////////////

Yi 
= {};
Yi.Utils 
= {};
Yi.Utils.execute 
= function(o){
         
if(typeof o != 'function')
                   eval(o)();
         
else
                   o();
}
//工作类
Yi.Workflow 
= function(workflowDef){
         
this.def = workflowDef;
         
this.tasks = this.def.tasks;
}
//public按照环节id查找查找
Yi.Workflow.prototype.findTask 
= function(taskId){
         
for(var i=0;i<this.tasks.length;i++){
                   
if(this.tasks[i].id == taskId)
                            
return this.tasks[i];
         }
}
//public启动工作?/span>
Yi.Workflow.prototype.start 
= function(){
         
this.currentTasks = [];
         Yi.Utils.execute(
this.def.start.fn);
         
for(var i=0;i<this.def.start.next.length;i++){
                   
this.currentTasks[i] = this.findTask(this.def.start.next[i]);
                   Yi.Utils.execute(
this.currentTasks[i].before);
         }
}
//private
Yi.Workflow.prototype.findCurrentTaskById 
= function(taskId){
         
for(var i=0;i<this.currentTasks.length;i++){
                   
if(this.currentTasks[i].id == taskId)
                            
return this.currentTasks[i];
         }
         
return null;
}
//private
Yi.Workflow.prototype.removeFromCurrentTasks 
= function(task){
         
var temp = [];
         
for(var i=0;i<this.currentTasks.length;i++){
                   
if(!(this.currentTasks[i] == task))
                            temp.push(
this.currentTasks[i]); 
         }
         
this.currentTasks = temp;
         temp 
= null;
}
//public触发当前环节
Yi.Workflow.prototype.signal 
= function(taskId){
         
//只处理当前活动环?/span>
         
var task = this.findCurrentTaskById(taskId);
         
if(task == null){
                   alert(
"工作未{到此环节!");
                   
return;
         }
         
//对于合ƈ的处?/span>
         
if(task.merge != undefined){
                   
if(task.merge != 0){
                            alert(
"工作流转条件不充分!");
                            
return;
                   }
else{
                            Yi.Utils.execute(task.before);
                   }        
         }
         
//触发当前环节
         Yi.Utils.execute(task.fn);
         
//触发后动?/span>
         Yi.Utils.execute(task.after);
         
//下一步如果工作流l束
         
if(task.next === "EOWF"){
                   Yi.Utils.execute(
this.def.end);
                   
delete this.currentTasks;
                   
return;
         }
         
//遍历下一步环?/span>
         
this.removeFromCurrentTasks(task);
         
for(var i=0;i<task.next.length;i++){
                   
var tempTask = this.findTask(task.next[i]);
                   
if(!tempTask.inCurrentTasks)
                            
this.currentTasks.push(tempTask);
                   
if(tempTask.merge != undefined){
                            tempTask.merge
--;
                            tempTask.inCurrentTasks 
= true;
                   }
                   
else
                            Yi.Utils.execute(tempTask.before);
         }
}
//public获取当前的活动环?/span>
Yi.Workflow.prototype.getCurrentTasks 
= function(){
         
return this.currentTasks;
}
//public获取程定义
Yi.Workflow.prototype.getDef 
= function(){
         
return this.def;
}

 

////////应用pȝ///////////////
var wf = new Yi.Workflow(workflowDef);
alert(
"启动工作?/span>");
wf.start();
alert(
"试手工执行d3,q回工作没有流转到q里");
wf.signal(
"task3");
alert(
"分支开?/span>");
alert(
"手工执行d1");
wf.signal(
"task1");
alert(
"手工执行d2");
wf.signal(
"task2");
alert(
"手工执行d4");
wf.signal(
"task4");
alert(
"手工执行d5");
wf.signal(
"task5");
alert(
"手工执行d3");
wf.signal(
"task3");
function begin(){
         alert(
"程开始,该函数在外部定义");
}
function end(){
         alert(
"程l束");
}


杨一 2009-03-06 17:39 发表评论
]]>
վ֩ģ壺 ³| ̫| | | ƽ| IJ| | Դ| | | | ͼ| | ³| | | ˮ| | | ̨ɽ| | ڳ| Դ| ɰ| | Ǩ| | | | ij| Դ| żҿ| ɽ| մ| ؿ˹| | | | | | |