﻿<?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-庄周梦蝶，孰蝶是我，我是孰蝶？一梦至今，蝶我已难分-随笔分类-java</title><link>http://www.blogjava.net/killme2008/category/19800.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 31 May 2008 15:45:01 GMT</lastBuildDate><pubDate>Sat, 31 May 2008 15:45:01 GMT</pubDate><ttl>60</ttl><item><title>两段代码的比较</title><link>http://www.blogjava.net/killme2008/archive/2008/05/31/204866.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 31 May 2008 09:25:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/05/31/204866.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/204866.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/05/31/204866.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/204866.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/204866.html</trackback:ping><description><![CDATA[第一个程序：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.ArrayList;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.List;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;TailRecursionTest&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TailRecursionTest&nbsp;t&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;TailRecursionTest();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10000</span><span style="color: #000000;">;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.a(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;a(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;j)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Integer</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">100000</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;对list进行处理<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
&nbsp;&nbsp;&nbsp; 没啥特殊的，仅仅是为了测试，我们将a方法调用10000次，a方法创建一个有100000个元素的list的局部变量。<br />
第二个程序：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.ArrayList;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.List;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;TailRecursionTest2&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TailRecursionTest2&nbsp;t&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;TailRecursionTest2();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.a(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;a(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;j)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(j&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10000</span><span style="color: #000000;">)<br />
&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;List&nbsp;list&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Integer</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">100000</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;对list进行处理<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a(j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
&nbsp;&nbsp;&nbsp; 也没啥特殊的，就是将循环换成了递归，a方法做的事情没变。两个都跑一下，程序1顺利结束，程序2出问题了，啥问题？如下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">161</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">162</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">163</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">164</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">165</span><span style="color: #000000;"><br />
Exception&nbsp;in&nbsp;thread&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">main</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;java.lang.OutOfMemoryError:&nbsp;Java&nbsp;heap&nbsp;space<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.util.ArrayList.</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">init</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at TailRecursionTest2.a(TailRecursionTest2.java:</span><span style="color: #000000;">17</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at TailRecursionTest2.a(TailRecursionTest2.java:</span><span style="color: #000000;">20</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at TailRecursionTest2.a(TailRecursionTest2.java:</span><span style="color: #000000;">20</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at TailRecursionTest2.a(TailRecursionTest2.java:</span><span style="color: #000000;">20</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at TailRecursionTest2.a(TailRecursionTest2.java:</span><span style="color: #000000;">20</span><span style="color: #000000;">)</span></div>
&nbsp;&nbsp; 我倒，才运行166次了，heap就满了。问题在哪呢？oh,yep，你肯定想到了，是不是重复创建list这个大集合引起的呢？它不是局部变量吗？怎么也会溢出？是的，list是局部变量，在a的方法栈里引用着，指向heap上的大对象，更关键的问题在于，java是没有尾递归优化的，递归方法是不会使用同一个栈帧，每一次递归调用，都将压入新的栈帧，并且这个栈帧上又new了一个list变量，引用着heap上新的一个大集合。随着栈深度的增加，jvm里维持着一条长长的方法调用轨迹以便你能回来，在方法没有返回之前，这些list变量一直被各自的栈帧引用着，不能被GC，你说，能不OOM吗？<br />
&nbsp;&nbsp;&nbsp; 也许，你想到了个补救方法来挽救程序2，就是每次在处理完list后，我把它设置为null，不让栈帧继续引用着它，咱编写对gc友好的代码，这不就行了，试试：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.ArrayList;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.List;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;TailRecursionTest2&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TailRecursionTest2&nbsp;t&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;TailRecursionTest2();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.a(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;a(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;j)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(j&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10000</span><span style="color: #000000;">)<br />
&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;List&nbsp;list&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Integer</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(</span><span style="color: #000000;">100000</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;对list进行处理<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">gc友好</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a(j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
&nbsp;&nbsp;&nbsp; 得意洋洋，我跑一下看看，这次跑到4000多次，但是：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><span style="color: #000000;">......<br />
4289</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">4290</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">4291</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">4292</span><span style="color: #000000;"><br />
java.lang.StackOverflowError<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.nio.cs.ext.DoubleByteEncoder.encodeArrayLoop(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.nio.cs.ext.DoubleByteEncoder.encodeLoop(Unknown&nbsp;Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.nio.charset.CharsetEncoder.encode(Unknown&nbsp;Source)</span></div>
&nbsp;&nbsp;&nbsp; 没办法啊，人家sun的jdk就是不支持尾递归优化，很不给你面子的栈溢出了。ibm的jdk据说支持尾递归优化，上面这个程序在ibm的jdk上可能可以正常结束，未经测试。<br />
<br />
总结：在java里，递归最好咱还是别用，老老实实地while、for；就算递归了，最好递归方法不要new太大的对象，除非你能确定递归的深度不是那么大。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/204866.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-05-31 17:25 <a href="http://www.blogjava.net/killme2008/archive/2008/05/31/204866.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Insect Workflow</title><link>http://www.blogjava.net/killme2008/archive/2008/05/21/201911.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 21 May 2008 07:09:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/05/21/201911.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/201911.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/05/21/201911.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/201911.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/201911.html</trackback:ping><description><![CDATA[<a target=""></a>
&nbsp;&nbsp;&nbsp; 今天整理代码，发现一个去年写的简单的工作流引擎，基于petri网（参考这里的<a href="http://www.blogjava.net/killme2008/category/19902.html">笔记</a>)，实现了顺序、并行、循环和选择四种路由，资源也实现了人工驱动和定时、延迟时间驱动；目前只实现了将工作流数据保存在内存的版本，然后就换工作，折腾着就忘了这个事儿，本来是计划加入数据库存储的。尽管只是个toy，可能对工作流感兴趣，或者想自己实现一个玩玩的朋友有参考价值，放到了google code上，svn地址：<br />
<tt><strong><em>&nbsp;http</em></strong>://insectworkflow.googlecode.com/svn/trunk/<br />
<br />
&nbsp;&nbsp;&nbsp; 源码中有在example包下给了个请假的例子，流程定义文件就是processes包下的leave.xml，实现大概是这么个流程：<br />
填写假单-》提交假单-and-split节点-》项目经理审批-》and-join节点-》结束<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;&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 />
<br />
其中项目经理审批和部门经理审批是并行路由。xml配置大概这样：<br />
</tt>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">node&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="and-split"</span><span style="color: #ff0000;">&nbsp;name</span><span style="color: #0000ff;">="and-split"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="2"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="3"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="4"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="5"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">node</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">node&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="dept_manager_confirm"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="3"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">resource&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="com.google.code.insect.workflow.impl.Group"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="2"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name</span><span style="color: #0000ff;">="dept_manager"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">resource</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">conditions&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="and"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">condition<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="com.google.code.insect.workflow.impl.NullHandler"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="false"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;variable-name</span><span style="color: #0000ff;">="LeaveInfo"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">conditions</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">handler<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="com.google.code.insect.workflow.example.leave.SendRemindHandler"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="4"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="6"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">node</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">node&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="project_manager_confirm"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="4"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">resource&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="com.google.code.insect.workflow.impl.Group"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="3"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name</span><span style="color: #0000ff;">="project_manager"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">resource</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">conditions&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="and"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">condition<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="com.google.code.insect.workflow.impl.NullHandler"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="false"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;variable-name</span><span style="color: #0000ff;">="LeaveInfo"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">conditions</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">handler<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="com.google.code.insect.workflow.example.leave.SendRemindHandler"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="5"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="7"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">node</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">node&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="and-join"</span><span style="color: #ff0000;">&nbsp;name</span><span style="color: #0000ff;">="and-join"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="5"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">handler<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="com.google.code.insect.workflow.example.leave.ResultHandler"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="6"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="7"</span><span style="color: #0000ff;">&gt;&lt;/</span><span style="color: #800000;">place</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="8"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">node</span><span style="color: #0000ff;">&gt;</span></div>
<br />
<tt>&nbsp;&nbsp;&nbsp; 其中的place就是各个Transition的输入或者输出库所，所谓node其实就是变迁（transition)，每个变迁对应一个handler，执行具体的业务操作，比如这里的com.google.code.insect.workflow.example.leave.SendRemindHandler 用于发送提醒消息给经理们。<br />
<br />
&nbsp;&nbsp;&nbsp; 具体调用和工作项的人工触发：<br />
<br />
</tt>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">//</span><span style="color: #008000;">初始化工作流管理器</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">WorkFlowManager&nbsp;wm&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;BasicWorkflowManager();<br />
wm.setConfiguration(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;DefaultConfiguration());<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">启动一个案例</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">Token&nbsp;token&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;wm.startWorkFlow(</span><span style="color: #000000;">"</span><span style="color: #000000;">leave</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
token.setAttribute(</span><span style="color: #000000;">"</span><span style="color: #000000;">LeaveInfo</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;leaveInfo);<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">提交假单</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">wm.doAction(token.getId(),&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.dennis,&nbsp;</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;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;leaveInfo.getStaff_name()&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">申请请假，请批准!</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">将token的id传递给后续节点做处理。。token的id就是案例id<br />
</span></div>
&nbsp;&nbsp;&nbsp; processes包下面的流程定义文件和test包下的TestUnit，分别测试了四种路由和定时、延时触发，有兴趣的可以看一下。<br />
<tt><br />
</tt><img src ="http://www.blogjava.net/killme2008/aggbug/201911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-05-21 15:09 <a href="http://www.blogjava.net/killme2008/archive/2008/05/21/201911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Rope来高效处理长字符串</title><link>http://www.blogjava.net/killme2008/archive/2008/05/05/198532.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 05 May 2008 10:41:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/05/05/198532.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/198532.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/05/05/198532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/198532.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/198532.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 前段时间看了这篇文章《<a href="http://www.ibm.com/developerworks/cn/java/j-ropes/index.html">Ropes：理论与实践</a>》。这两天为了提高工作中某个系统对外接口的效率，才认真学习了一番。本质上Ropes是将字符串表示为一棵二叉树，特别适用于长字符串的处理，貌似c++ STL库中也有这么个实现。具体实现和原理还是看这篇<a href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">paper</a>。《<a href="http://www.ibm.com/developerworks/cn/java/j-ropes/index.html">Ropes：理论与实践</a>》一文中给出的测试数据相当惊人，Ropes比之String和StringBuffer在append,insert,delete等操作上的效率都有一个数量级以上的差距。跑下作者给出的测试程序，其实在测试的字符串不是很长的情况下，这个差距并没有那么大，这也从侧面说明了Rope的应用范围：即只有在大量修改大型字符串的应用程序中才能看到明显的性能提升。那么是否可以用Rope替代StringBuffer做append生成字符串（比如我要的生成xml)。作者也说啦：<br />
&nbsp; &#8220;由于 <code>Rope</code> 的附加性能通常比 <code>StringBuffer</code> 好，这时使用 rope
是否有意义呢？答案还是否。不论何时将输入的数据组合在一起形成格式化输出时，最漂亮最有效的方法是使用模板引擎（例如 StringTemplate
或 FreeMarker）。这种方法不仅能干净地将表示标记与代码分开，而且模板只进行一次编译（通常编译为 JVM
字节码），以后可以重用，从而使它们拥有极佳的性能特征。&#8221;<br />
<br />
&nbsp;&nbsp;&nbsp; 我用Rope for java替代了StringBuffer做XML生成，效率提升在5%-30%左右，xml字符串不是很长，这个提升显然有限，也带来了不必要的复杂度。因此最后还是用Velocity模板引擎来生成XML，测试的结果效率并没有多少改善，但是显然更容易维护和开发了。回到Rope的话题，我用Ruby实现了个版本，Rubyforge上有一个Rope的实现，但是看了源码，与paper所述算法有点差异，因此照着Rope for java也实现了一个<a href="http://code.google.com/p/rope4r/">Rope4r</a>。测试的结果证明在长字符串的累积操作上，Rope4r的append比之String的+=性能可以快上3倍左右，而如果采用String的&lt;&lt;操作，不是immutable的，当然是最快了；比较郁闷的是slice和insert操作都比String的慢上几倍，因为Ruby的String、Array的内建对象都是直接用c写成并做了优化的，我猜测原因在这。<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/198532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-05-05 18:41 <a href="http://www.blogjava.net/killme2008/archive/2008/05/05/198532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一切为了跨平台</title><link>http://www.blogjava.net/killme2008/archive/2008/04/22/194849.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 22 Apr 2008 10:12:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/22/194849.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/194849.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/22/194849.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/194849.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/194849.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 推荐两篇blog：<br />
<a href="http://blog.csdn.net/haoel/archive/2008/03/27/2224055.aspx">《java NIO 类库selector机制解析（上）》</a><br />
<a href="http://blog.csdn.net/haoel/archive/2008/03/27/2224069.aspx">《java NIO 类库selector机制解析（下）》</a><br />
<br />
&nbsp;&nbsp;&nbsp; 有一个奇怪的现象引出的话题，为了<font size="3"><font face="Times New Roman">Selector.wakeup功能做到跨平台，</font></font><font size="3"><span style="font-family: 宋体;" lang="ZH-CN">每个</span><font face="Times New Roman">Selector.open()</font><span style="font-family: 宋体;" lang="ZH-CN">时，在</span><font face="Times New Roman">Windows</font><span style="font-family: 宋体;" lang="ZH-CN">会建立一对自己和自己的</span><font face="Times New Roman">loopback</font><span style="font-family: 宋体;" lang="ZH-CN">的</span><font face="Times New Roman">TCP</font><span style="font-family: 宋体;" lang="ZH-CN">连接；在</span><font face="Times New Roman">Linux</font><span style="font-family: 宋体;" lang="ZH-CN">上会开一对</span><font face="Times New Roman">pipe</font><span style="font-family: 宋体;" lang="ZH-CN">（</span><font face="Times New Roman">pipe</font><span style="font-family: 宋体;" lang="ZH-CN">在</span><font face="Times New Roman">Linux</font><span style="font-family: 宋体;" lang="ZH-CN">下一般都是成对打开）。</span></font>java为了跨平台真是无所不用其极，此中冷暖谁知啊。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/194849.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-22 18:12 <a href="http://www.blogjava.net/killme2008/archive/2008/04/22/194849.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用jprofiler监控jruby脚本</title><link>http://www.blogjava.net/killme2008/archive/2008/03/24/188253.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 24 Mar 2008 07:26:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/03/24/188253.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/188253.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/03/24/188253.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/188253.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/188253.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; jruby本质上也是启动一个jvm，然后去读Ruby脚本并解释执行（也可以编译），因此jprofiler理所当然也可以去监控jruby脚本的执行。<br />
执行&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;hello.rb</span></div>
等价于执行：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">java&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Xmx378m&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Xss1024k&nbsp;&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.home</span><span style="color: #000000;">=/</span><span style="color: #000000;">usr</span><span style="color: #000000;">/</span><span style="color: #000000;">local</span><span style="color: #000000;">/</span><span style="color: #000000;">jruby </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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -</span><span style="color: #000000;">Djruby.lib</span><span style="color: #000000;">=/</span><span style="color: #000000;">usr</span><span style="color: #000000;">/</span><span style="color: #000000;">local</span><span style="color: #000000;">/</span><span style="color: #000000;">jruby</span><span style="color: #000000;">/</span><span style="color: #000000;">lib&nbsp;Djruby.script</span><span style="color: #000000;">=</span><span style="color: #000000;">jruby&nbsp;org.jruby.Main&nbsp;hello.rb</span></div>
这一点，你可以通过ps aux |grep jruby 看到。因此配置jprofiler就简单了，在VM arguments加上这些参数（可以包括jruby的参数），比如我的VM arguments配置如下：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">-</span><span style="color: #000000;">server&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Xmx378m&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Xss1024k&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.script</span><span style="color: #000000;">=</span><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.thread.pooling</span><span style="color: #000000;">=</span><span style="color: #000000;">true <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.jit.threshold</span><span style="color: #000000;">=</span><span style="color: #000000;">0&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.compile.fastest</span><span style="color: #000000;">=</span><span style="color: #000000;">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; -</span><span style="color: #000000;">Djruby.home</span><span style="color: #000000;">=</span><span style="color: #000000;">D:\jruby\jruby</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">.1RC2&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.lib</span><span style="color: #000000;">=</span><span style="color: #000000;">D:\jruby\jruby</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">.1RC2\lib</span></div>
<br />
Main class or executable JAR填上：org.jruby.Main。然后就是Arguments一栏填上你的脚本位置：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">D:\ruby\lib\hello.rb</span></div>
<br />
最后，别忘了将jruby/lib目录下的bsf.jar和jruby.jar加入Class Path。<br />
<br />
大功告成，你可以用jprofiler去观察GC、线程和锁、Heap等等了。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/188253.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-03-24 15:26 <a href="http://www.blogjava.net/killme2008/archive/2008/03/24/188253.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Grizzly——不走寻常路的nio框架</title><link>http://www.blogjava.net/killme2008/archive/2008/02/23/181623.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 23 Feb 2008 11:13:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/23/181623.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/181623.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/23/181623.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/181623.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/181623.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 在《程序员》最新一期有个专题介绍java开源nio框架，其中谈到了mina和grizzly。mina我还算比较熟悉，写过一些代码，也尝试去读过源码。而grizzly是第一次听说，这个项目是sun的一个开源nio框架，是2004年在GlassFish项目中诞生的，一开始是一个http web server，用于取代Tomcat的Coyote Connector和Sun WebServer，2007年7月1.5版本发布并宣布成为开源项目，项目主页在<a href="https://grizzly.dev.java.net">https://grizzly.dev.java.net</a><br />
&nbsp;&nbsp;&nbsp; <strong>grizzly与mina</strong>的性能比较（基于2007年JavaOne会议上的ppt)<br />
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/grizzly1.jpg" alt="" border="0" /><br />
<br />
&nbsp;&nbsp;&nbsp; <strong>GlassFish vs Tomcat</strong><br />
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/grizzly2.jpg.jpg" alt="" border="0" /><br />
<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; grizzly的设计与一般的nio框架相比是比较不同的，主要不同点在于<strong>读和写都是采用blocking方式，并且使用临时selector</strong>；线程模型可配置，不过据作者介绍在跑一个selector主线程处理ACCEPT，用线程池处理read和write性能表现最好，这点不出意料。<br /><img src ="http://www.blogjava.net/killme2008/aggbug/181623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-23 19:13 <a href="http://www.blogjava.net/killme2008/archive/2008/02/23/181623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>保持java线程间可见性的5种方式</title><link>http://www.blogjava.net/killme2008/archive/2008/02/23/181560.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 23 Feb 2008 02:44:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/23/181560.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/181560.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/23/181560.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/181560.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/181560.html</trackback:ping><description><![CDATA[<table>
    <tbody>
        <tr>
            <th>Primitive </th>
            <th>Writes up to and including&#8230; </th>
            <th>...are made visible to&#8230;</th>
        </tr>
        <tr>
            <td> Object </td>
            <td> the end of a synchronized block or method </td>
            <td> a thread entering a synchronized block or method for the same object. </td>
        </tr>
        <tr>
            <td> Volatile field </td>
            <td> a write to a volatile field </td>
            <td> any thread reading that volatile field. </td>
        </tr>
        <tr>
            <td> Thread </td>
            <td> a call to <code>Thread.start</code> </td>
            <td> the newly started thread. </td>
        </tr>
        <tr>
            <td> Thread </td>
            <td> the final write made by a dying thread </td>
            <td> any thread which <em>successfully</em> calls <code>Thread.join</code> on that thread. </td>
        </tr>
        <tr>
            <td> Final field </td>
            <td> the initialization of a final field (but only those writes affecting the field and any object it references) </td>
            <td> any thread, provided that the constructor of the object containing the field doesn&#8217;t write the value of <code>this</code> anywhere eventually visible to other threads</td>
        </tr>
    </tbody>
</table>
<br />
<br />
&nbsp; 这些在《java并发编程实践》一书中已经有详细解释，特别是对于ReentrantLock、volatile域以及final域的讨论。今天在MenTaLguY的blog上看到这张表，摘录下。<img src ="http://www.blogjava.net/killme2008/aggbug/181560.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-23 10:44 <a href="http://www.blogjava.net/killme2008/archive/2008/02/23/181560.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java nio之Buffer(一)</title><link>http://www.blogjava.net/killme2008/archive/2008/02/22/181357.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 22 Feb 2008 06:31:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/22/181357.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/181357.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/22/181357.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/181357.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/181357.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; Buffer是一个包装了基本数据元素数组的对象，它以及它的子类定义了一系列API用于处理数据缓存。<br />
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/buffer.JPG" alt="" border="0" /><br />
一、属性<br />
Buffer有四个基本属性：<br />
1、capacity&nbsp; 容量，buffer能够容纳的最大元素数目，在Buffer创建时设定并不能更改<br />
2、limit buffer中有效位置数目<br />
3、position 下一个读或者写的位置<br />
4、mark&nbsp; 用于记忆的标志位，配合reset()使用，初始值未设定，调用mark后将当前position设为值<br />
<br />
四者关系：0 &lt;= mark &lt;= position &lt;= limit &lt;= capacity<br />
<br />
二、API<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;java.nio;<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Buffer&nbsp;{<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;capacity(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;position(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Buffer&nbsp;position&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;newPosition)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;limit(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Buffer&nbsp;limit&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;newLimit)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Buffer&nbsp;mark(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Buffer&nbsp;reset(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Buffer&nbsp;clear(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Buffer&nbsp;flip(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Buffer&nbsp;rewind(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;remaining(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;hasRemaining(&nbsp;)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;isReadOnly(&nbsp;);<br />
}</span></div>
<br />
支持链式调用，如：buffer.mark().position(5).reset( );<br />
注意isReadOnly()方法决定了buffer是否可写。<br />
<br />
三、操作<br />
&nbsp; 以ByteBuffer为例，<br />
1、访问，通过get(),get(index),其中get()从当前position位置读取，get(index)从index位置读取，不改变当前position,下面要说到的put也一样。<br />
2、填充，通过put(byte),put(index,byte)，按照绝对位置填充也是不改变当前position属性<br />
<br />
3、flipping，试想，我们将填充完毕的buffer传递给socket输出，那么socket读取是依据position属性确定，就会从结尾后一位开始读，这样肯定是不正确的，如果要正确的读取我们先要：<br />
&nbsp; buffer.limit(buffer.position( )).position(0);<br />
将limit设为position,
将position设为0，这个操作就叫flipping，API直接提供了这个操作：<br />
&nbsp; buffer.flip( );<br />
特别注意，<strong>flip()方法会改变limit属性，将limit属性从capacity设置为当前position。</strong>rewind()方法与flip()类似，但是仅将position设为0，而不改变limit，通常用于重新读取已经被flip的buffer。<strong>flip()另一个注意点是，两次调用buffer的flip方法，将使得position和limit属性都为0。</strong><br />
<br />
4、迭代取元素：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;buffer.hasRemaining(&nbsp;),&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
myByteArray&nbsp;[i]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;buffer.get(&nbsp;);<br />
}<br />
<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;count&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;buffer.remaining(&nbsp;);<br />
</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;count,&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
myByteArray&nbsp;[i]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;buffer.get(&nbsp;);<br />
}</span></div>
ByteBuffer不是线程安全的，前一种方式适合并发访问，后一种方式效率更高。这两种方式都是一个一个取，效率都比批量取低。<br />
<br />
5.clear()方法，将buffer重设为空状态，也就是设置limit=capacity,position=0，以便重复利用。<br />
<br />
6.compact()方法，用于压缩buffer，这个方法在多次重复调用时是比较低效。<br />
<br />
7.mark(),初始是未定义的，这适合如果调用reset将抛出InvalidMarkException。调用makr()后，将当前position设为mark以便reset时返回。注意，rewind( ), clear( ), and flip( )方法都将丢弃已经创建的mark。调用limit(index),positioon(index)，如果index的值小于当前mark，mark也将被丢弃。<br />
<br />
8.比较，可以通过equals()和compateTo()方法来比较两个buffer，前一个返回boolean，后一个返回0，-1，1。两个buffer equal的条件是：<br />
1）类型相同<br />
2）剩余元素的数目相等<br />
3）剩余元素也一一相等<br />
<br />
9、批量移动数据，为了更有效地进行数据传送，批量的数据存取肯定是不能少的，Buffer及其子类都有提供类似的方法，比如CharBuffer:<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;CharBuffer&nbsp;get&nbsp;(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;[]&nbsp;dst)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;CharBuffer&nbsp;get&nbsp;(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;[]&nbsp;dst,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;offset,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;length)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;CharBuffer&nbsp;put&nbsp;(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">[]&nbsp;src)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;CharBuffer&nbsp;put&nbsp;(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;[]&nbsp;src,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;offset,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;length)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;CharBuffer&nbsp;put&nbsp;(CharBuffer&nbsp;src)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;CharBuffer&nbsp;put&nbsp;(String&nbsp;src)<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;CharBuffer&nbsp;put&nbsp;(String&nbsp;src,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;start,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;end)</span></div>
<br />
四、创建Buffer<br />
&nbsp;&nbsp;&nbsp; Buffer以及其子类都无法直接new，而必须把通过他们提供的工厂方法来创建。通常有两种方式：<br />
1、allocate，例如<br />
CharBuffer charBuffer = CharBuffer.allocate (100);<br />
将在堆上分配一个可以存储100个字符的数组作为backing store。<br />
<br />
2、wrap，包装一个已有的数组：<br />
char [] myArray = new char [100];<br />
CharBuffer charbuffer = CharBuffer.wrap (myArray);<br />
注意,这样的方式创建的Buffer，将不会在堆上创建新的数组，而是直接利用myArray做backing store，这意味着任何对myArray或者buffer的修改都将影响到buffer或者myArray。可以通过public final boolean hasArray( )方法来判断是否拥有一个数组，通过array()方法取得这个数组。<br />
<br />
五、复制Buffer<br />
&nbsp;&nbsp; 其实这个复制也是&#8220;浅拷贝&#8221;，通过duplicate()方法将返回一个新创建的buffer，这个新buffer与原来的Buffer<strong>共享数据，一样的capacity，但是有自己的position、limit和mark属性。</strong>通过asReadOnlyBuffer()方法复制的buffer与duplicate()类似，但是是<strong>只读</strong>的，不能调用put。比较特别的是slice()方法，故名思议，类似切割一个Buffer出来，与duplicate类似，但是它将从原来Buffer的当前position开始，并且capacity等于原来Buffer的剩余元素数目，也就是(limit-position)。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/181357.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-22 14:31 <a href="http://www.blogjava.net/killme2008/archive/2008/02/22/181357.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JRuby 1.1 RC2  Released</title><link>http://www.blogjava.net/killme2008/archive/2008/02/18/180388.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 18 Feb 2008 01:43:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/18/180388.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/180388.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/18/180388.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/180388.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/180388.html</trackback:ping><description><![CDATA[<p>修正了很多bug，我关注的
JRUBY-1686也得到了修正，距离1.1的发布不远了。</p>
<p>The JRuby community is pleased to announce the release of JRuby 1.1 RC 2</p>
<p>Homepage: <a href="http://www.jruby.org/" rel="nofollow">http://www.jruby.org/</a><br />
Download: <a href="http://dist.codehaus.org/jruby/" rel="nofollow">http://dist.codehaus.org/jruby/</a></p>
<p>JRuby 1.1RC2 is the second release candidate of JRuby 1.1.&nbsp; JRuby 1.1<br />
represents a concerted focus on speed and refinement.&nbsp; <a title="" href="http://www.ruby-lang.org" >ruby</a> code can<br />
completely compile in an Ahead Of Time (AOT) or Just In Time (JIT) mode;<br />
yielding a faster <a title="" href="http://www.ruby-lang.org" >ruby</a>!&nbsp; It also uses less memory than our previous releases.</p>
<p>We need people to download JRuby 1.1RC2 and give us feedback.&nbsp; Test your<br />
applications and help us make JRuby 1.1 a great release.</p>
<p>Highlights:<br />
- 260 issues resolved since JRuby 1.1RC1<br />
- Large IO refactoring<br />
<strong>
- Memory improvements for JIT'd methods:<br />
&nbsp; - Control total number of methods JIT'd<br />
&nbsp; - Support a JIT cache between runtimes to return permgen<br />
&nbsp; - Reduce codesize of generated methods (50-70% reduction)</strong></p><img src ="http://www.blogjava.net/killme2008/aggbug/180388.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-18 09:43 <a href="http://www.blogjava.net/killme2008/archive/2008/02/18/180388.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JRuby中使用接口和抽象类</title><link>http://www.blogjava.net/killme2008/archive/2008/02/15/180078.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 15 Feb 2008 06:34:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/15/180078.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/180078.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/15/180078.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/180078.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/180078.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 要在JRuby中实现java接口，接口<strong>include</strong>进来，实现接口方法即可，例如实现java.lang.Runnable接口做线程处理：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">require 'java'<br />
include_class 'java.lang.Runnable'<br />
class</span><span style="color: #000000;">&nbsp;TestRunnable<br />
&nbsp;&nbsp;&nbsp;&nbsp;include&nbsp;Runnable<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;initialize(name)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@name</span><span style="color: #000000;">=</span><span style="color: #000000;">name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;run<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">hello,</span><span style="color: #800000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">@name<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
end<br />
</span></div>
<br />
&nbsp;&nbsp;&nbsp; 要在JRuby中继承抽象类，实现其中的抽象方法，方法稍微麻烦点，需要cglib，到<a href="http://sourceforge.net/project/showfiles.php?group_id=56933">这里</a>下载cglib-nodep-2.1_3.jar，写个通用库abstract_class.rb方便处理:<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">load&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">cglib-nodep-2.1_3.jar</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Object<br />
&nbsp;&nbsp;include&nbsp;Java<br />
&nbsp;&nbsp;include_class&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">net.sf.cglib.proxy.Enhancer</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;include_class&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">net.sf.cglib.proxy.NoOp</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">self<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;method_missing(mname,&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">args,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unless&nbsp;mname&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;:abstract_impl&nbsp;</span><span style="color: #0000ff;">and</span><span style="color: #000000;">&nbsp;respond_to?(:java_class)&nbsp;</span><span style="color: #0000ff;">and</span><span style="color: #000000;">&nbsp;JavaLang::reflect::Modifier.isAbstract(JavaLang::Class.for_name(java_class.name).modifiers)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super<br />
&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;generate_abstract_impl(args,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;generate_abstract_impl(args,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;factory&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Enhancer.new<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;factory.setSuperclass(java_class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;factory.setInterfaces(java_class.interfaces.to_java(</span><span style="color: #800000;">"</span><span style="color: #800000;">java.lang.Class</span><span style="color: #800000;">"</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;factory.setCallback(NoOp::INSTANCE)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;object_args&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;args.map&nbsp;{&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">arg</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;Java.ruby_to_java(arg)&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class_arguments&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;object_args.map&nbsp;{</span><span style="color: #000000;">|</span><span style="color: #000000;">arg</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;arg.java_class}.to_java(</span><span style="color: #800000;">"</span><span style="color: #800000;">java.lang.Class</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generated_class&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;factory.create(class_arguments,&nbsp;object_args.to_java(</span><span style="color: #800000;">"</span><span style="color: #800000;">java.lang.Object</span><span style="color: #800000;">"</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ruby_class&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Class.new(generated_class.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ruby_class.class_eval(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ruby_class.new(</span><span style="color: #000000;">*</span><span style="color: #000000;">args)<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;<br />
end</span></div>
<br />
&nbsp;&nbsp;&nbsp; 使用的话，require一下abstract_class，例如我们要继承java.util.TimerTask，实现其中的run方法：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">$:.unshift&nbsp;File.join(File.dirname(</span><span style="color: #800080;">__FILE__</span><span style="color: #000000;">),</span><span style="color: #800000;">'</span><span style="color: #800000;">.</span><span style="color: #800000;">'</span><span style="color: #000000;">)<br />
require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">java</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">abstract_class</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.TimerTask<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.Timer<br />
timer_task&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;TimerTask.abstract_impl&nbsp;do<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;run<br />
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">timer&nbsp;task</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;end<br />
end<br />
<br />
Timer.new.schedule(timer_task,&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">)<br />
</span></div>
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/180078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-15 14:34 <a href="http://www.blogjava.net/killme2008/archive/2008/02/15/180078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JRuby的性能优化(update)</title><link>http://www.blogjava.net/killme2008/archive/2008/01/31/178725.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 31 Jan 2008 10:58:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/01/31/178725.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/178725.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/01/31/178725.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/178725.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/178725.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 越来越觉的JRuby是个很有前途的项目，结合Ruby的性感语法和java极其丰富的类库，况且有团队持续不断地修正bug、改进性能，这样的玩意完全有成为&#8220;少男杀手&#8221;的潜质。JRuby wiki上列出了性能优化的四条建议：<br />
1、调优编译器，JRuby早就弃暗投明跟随XRuby走上了编译这条牛B的道路，将Ruby Script编译成字节码，因此这个环节是断断不能忽略的。<br />
两种编译方式：<br />
AOT模式：直接生成class文件，脱了Ruby这层皮，咱就是人见人&#8220;爱&#8221;的java了。<br />
JIT模式：充分利用成熟的jit技术，咱不全脱，朦胧美才是真的美。默认从0.9.9版本开始就是开启的，关闭的话（要我说还不如全脱）<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">J</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.jit.enabled</span><span style="color: #000000;">=</span><span style="color: #0000ff;">false</span></div>
<br />
<br />
2、关闭ObjectSpace<br />
ObjectSpace是Ruby用来操作所有运行时对象的模块，这个功能相当牛x。这个的实现在c ruby里是比较容易的，但是对于JRuby代价就比较昂贵了，其实就大部分情况下你基本用不到这个东东，那么最好就是关闭它，JRuby提供了<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">J</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.objectspace.enabled</span><span style="color: #000000;">=</span><span style="color: #0000ff;">false</span></div>
选项来关闭它。<br />
<br />
3、开启线程池<br />
我们知道，在c ruby中的线程是绿色的轻量级线程，因此运行时就动不动开个百来十个&#8220;线程&#8221;跑一跑充下款爷；然而在JRuby中，线程的实现那可是实打实的本地线程（也就是Ruby线程与java线程一比一），你这么动不动上百个线程那不慢才怪了。因此JRuby提供了线程池选项，运行时尽可能地满足你的要求开线程，但是当短命的Ruby线程重复创建的时候，这些线程将被复用，这在大多数情况下能提高性能表现，特别是在每次调用都启动一个线程的情况下。不过具体效果还是要测试的实际数据说话。<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">J</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.thread.pooling</span><span style="color: #000000;">=</span><span style="color: #0000ff;">true</span><span style="color: #000000;"> <br />
</span></div>
<br />
<br />
4、使用Java "server"模式虚拟机，地球淫都知道<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">J</span><span style="color: #000000;">-</span><span style="color: #000000;">server&nbsp;myscript.rb</span></div>
<br />
5、尽量使用最新的jdk，在我的测试中，jdk6跑jruby是效率最高的。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/178725.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-01-31 18:58 <a href="http://www.blogjava.net/killme2008/archive/2008/01/31/178725.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>介绍下smartclient</title><link>http://www.blogjava.net/killme2008/archive/2008/01/08/173663.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 08 Jan 2008 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/01/08/173663.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/173663.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/01/08/173663.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/173663.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/173663.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; <a href="http://www.smartclient.com/">smartclient</a>是一个企业级的ajax框架，包括非常出色的UI库、工具库和客户端服务端数据绑定等功能。smartclient本来是一个商业产品，
2007年11月7号才以LGPL协议开源。除了一些所见即所得的构建工具和企业级的可选组件外，其他都开源了。这个记的javaeye和infoq都有报道。<br />
&nbsp;&nbsp;&nbsp; 在接触smartclient以前，我还没有使用过类似的ajax ui库，比如现在很火的ext。smartclient给我的第一印象是非常漂亮的ui效果，有兴趣可以去它的官方<a href="http://www.smartclient.com/featureExplorer.jsp">demo</a>看看。smartclient的demo和文档做的非常出色，入手开发也非常容易。<br />
第一步：<a href="http://www.smartclient.com/product/download.jsp">下载LGPL版本</a>，并解压缩<br />
第二步：运行解压后目录下的\SmartClient_60_LGPL\smartclientSDK\start_embedded_server.bat，SDK自带了一个内嵌的tomcat<br />
第三步：访问 http://localhost:8080<br />
<br />
你将见到：<br />
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/smartclient.jpg" alt="" border="0" /><br />
<br />
这些demo本身就是用smartclient制作的。开发过程中你需要做就是查看examples和文档中的reference（api文档），基本没有解决不了的问题。<br />
<br />
人见人爱的Hello World例子：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">isc.Label.create({<br />
&nbsp;&nbsp;&nbsp;&nbsp;height:&nbsp;</span><span style="color: #000000;">50</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;styleName:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">helloWorldText</span><span style="color: #000000;">"</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;padding:&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;backgroundColor:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">#ffffd0</span><span style="color: #000000;">"</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;align:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">center</span><span style="color: #000000;">"</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;valign:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">center</span><span style="color: #000000;">"</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;wrap:&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;showEdges:&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;showShadow:&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;contents:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">Hello&nbsp;world!</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
})<br />
</span></div>
<br />
效果：<br />
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/smartclient2.jpg" alt="" border="0" /><br />
<br />
&nbsp;&nbsp;&nbsp; smartclient除了完整的UI组件，还包括丰富的动态效果库以及可选的皮肤等高级主题，不再展开了，毕竟贴图是在是挺麻烦的事情：）还不如有兴趣的自己翻demo。说了这么多优点，那么缺点是啥？你可能猜到了，性能！所有js UI库无法避免的问题，不过我没有其他UI库的使用经验，倒是不能给出个比较数据。我们写的东西的性能也只是堪堪能够接受。<br />
&nbsp;&nbsp; smartclient跟dwr可以说是天生一对，smartclient UI组件的数据源可以是xml也可以是json，如果采用json做交换格式，可以与dwr无缝结合，真正实现One Page,One Application（我们就是这样做的^_^)。<br />
<br />
<br />
<br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/173663.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-01-08 15:48 <a href="http://www.blogjava.net/killme2008/archive/2008/01/08/173663.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>介绍一个轻量级java的swf处理库</title><link>http://www.blogjava.net/killme2008/archive/2008/01/04/172690.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 04 Jan 2008 03:46:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/01/04/172690.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/172690.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/01/04/172690.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/172690.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/172690.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 提取swf文件元信息、压缩swf、解压swf都可以处理，来自于http://www.brooksandrus.com/blog/category/java/，或者直接<a href="http://www.blogjava.net/Files/killme2008/swf.rar">这里</a>下载。<br />
<br />
一个小例子：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SWFHeader&nbsp;header&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SWFHeader(</span><span style="color: #000000;">"G:\\mplayer\\test.swf"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">signature:&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getSignature());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">version:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getVersion());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">compression:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getCompressionType());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">size:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getSize());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">nbits:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getNbits());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">xmax:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getXmax());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">ymax:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getYmax());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">width:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getWidth());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">height:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getHeight());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">frameRate:&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getFrameRate());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">frameCount:&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;header.getFrameCount());</span></div>
&nbsp;<br />
压缩、解压缩，需要注意生成的文件将覆盖原文件：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">//</span><span style="color: #008000;">压缩</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">SWFCompressor&nbsp;compressor</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SWFCompressor(</span><span style="color: #000000;">"</span><span style="color: #000000;">G:\\mplayer\\test.swf</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">解压缩</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">SWFDecompressor&nbsp;decompressor</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SWFDecompressor(</span><span style="color: #000000;">"</span><span style="color: #000000;">G:\\mplayer\\test.swf</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/172690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-01-04 11:46 <a href="http://www.blogjava.net/killme2008/archive/2008/01/04/172690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PPT转图片(更新）</title><link>http://www.blogjava.net/killme2008/archive/2008/01/04/172680.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 04 Jan 2008 03:26:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/01/04/172680.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/172680.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/01/04/172680.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/172680.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/172680.html</trackback:ping><description><![CDATA[update:2008-05-05，POI已经可以处理这个需求：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;net.rubyeye.test;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.FileOutputStream;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;org.apache.poi.hslf.HSLFSlideShow;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;org.apache.poi.hslf.model.Picture;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;org.apache.poi.hslf.usermodel.PictureData;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;org.apache.poi.hslf.usermodel.SlideShow;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;PPTToImageConverter&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;Exception&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SlideShow&nbsp;ppt&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SlideShow(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;HSLFSlideShow(</span><span style="color: #000000;">"</span><span style="color: #000000;">D:/test.ppt</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;extract&nbsp;all&nbsp;pictures&nbsp;contained&nbsp;in&nbsp;the&nbsp;presentation</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PictureData[]&nbsp;pdata&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ppt.getPictureData();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;pdata.length;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PictureData&nbsp;pict&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;pdata[i];<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;picture&nbsp;data</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[]&nbsp;data&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;pict.getData();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;type&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;pict.getType();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;ext;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">switch</span><span style="color: #000000;">&nbsp;(type)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;Picture.JPEG:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ext&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">.jpg</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;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;Picture.PNG:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ext&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">.png</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;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;Picture.WMF:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ext&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">.wmf</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;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;Picture.EMF:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ext&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">.emf</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;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;Picture.PICT:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ext&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">.pict</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;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">default</span><span style="color: #000000;">:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">continue</span><span style="color: #000000;">;<br />
&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;FileOutputStream&nbsp;out&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;FileOutputStream(</span><span style="color: #000000;">"</span><span style="color: #000000;">D:/test/pict_</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;ext);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.close();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span></div>
<br />
&nbsp;&nbsp;  原文：<br />
&nbsp;&nbsp; 小结下最近做的东西吧。因为是做一个素材管理的东西，因此需要处理各种各样的素材，音频、视频、图片、pdf、ppt等等。遇到一个需求就是将PPT转成图片组，google一下，在java里是可以jcom之类的开源库实现，本质上都是通过jni调用office的COM接口来实现。我们就需要这么一个小功能，拖这么大个开源库进来实在没有必要。最后决定自己写个动态链接库，通过jni来调用。<br />
&nbsp;&nbsp;&nbsp; 先写工具类，<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;PPTUtils&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;PPTUtils()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">native</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;convertPPT2IMG(String&nbsp;pptFileName,&nbsp;String&nbsp;tmpDir);<br />
<br />
&nbsp;</span><span style="color: #0000ff;">&nbsp;&nbsp; public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;loadLibrary()&nbsp;{</span><span style="color: #008000;">//</span><span style="color: #008000;">加载动态库</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;dllFileName&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">pptDll</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;OsName&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;System.getProperty(</span><span style="color: #000000;">"</span><span style="color: #000000;">os.name</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(OsName.contains(</span><span style="color: #000000;">"</span><span style="color: #000000;">Windows</span><span style="color: #000000;">"</span><span style="color: #000000;">))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dllFileName&nbsp;</span><span style="color: #000000;">+=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">.dll</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dllFileName&nbsp;</span><span style="color: #000000;">+=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">.so</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&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;</span><span style="color: #008000;">//</span><span style="color: #008000;">加载动态链接库</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.load(</span><span style="color: #000000;">dllFileName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(Exception&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;&nbsp;&nbsp;LOG.error("can&nbsp;not&nbsp;load&nbsp;"&nbsp;+&nbsp;dllFileName&nbsp;+&nbsp;",&nbsp;"&nbsp;+&nbsp;e.getMessage());</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}</span></div>
<br />
&nbsp;&nbsp;&nbsp; 编译一下，执行javah PPTUtils生成头文件PPTUtils.h。接下来用vc写个动态链接库，记的将MSPPT.OLB（在office安装目录下）加入工程，新建一个ppt2img.cpp：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">stdafx.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">PPTUtils.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">msppt.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
<br />
JNIEXPORT&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;JNICALL&nbsp;Java_com_starnet_dmb_util_PPTUtils_convertPPT2IMG(JNIEnv&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">env, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jclass&nbsp;clazz,&nbsp;jstring&nbsp;pptFileName,&nbsp;jstring&nbsp;tmpDir){<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">初始化com</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(CoInitialize(&nbsp;NULL&nbsp;)&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;E_INVALIDARG)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AfxMessageBox(_T(</span><span style="color: #000000;">"</span><span style="color: #000000;">初始化Com失败!</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
&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;<br />
&nbsp;&nbsp;&nbsp;&nbsp;_Application&nbsp;&nbsp;&nbsp;app;<br />
&nbsp;&nbsp;&nbsp;&nbsp;Presentations&nbsp;&nbsp;&nbsp;prsts;<br />
&nbsp;&nbsp;&nbsp;&nbsp;_Presentation&nbsp;&nbsp;&nbsp;prst;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">jstring转成char&nbsp;*</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">ppt;<br />
&nbsp;&nbsp;&nbsp;ppt&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;env</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">GetStringUTFChars(pptFileName,</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">tmp;<br />
&nbsp;&nbsp;&nbsp;tmp</span><span style="color: #000000;">=</span><span style="color: #000000;">env</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">GetStringUTFChars(tmpDir,</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(</span><span style="color: #000000;">!</span><span style="color: #000000;">app.CreateDispatch(_T(</span><span style="color: #000000;">"</span><span style="color: #000000;">PowerPoint.Application</span><span style="color: #000000;">"</span><span style="color: #000000;">))){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AfxMessageBox(_T(</span><span style="color: #000000;">"</span><span style="color: #000000;">初始化PowerPoint失败!</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;prsts&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;app.GetPresentations();<br />
&nbsp;&nbsp;&nbsp;prst&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;prsts.Open(_T(ppt),</span><span style="color: #0000ff;">false</span><span style="color: #000000;">,</span><span style="color: #0000ff;">false</span><span style="color: #000000;">,</span><span style="color: #0000ff;">false</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;prst.SaveAs(_T(tmp),</span><span style="color: #000000;">17</span><span style="color: #000000;">,</span><span style="color: #0000ff;">false</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;app.ReleaseDispatch();<br />
&nbsp;&nbsp;&nbsp;app.Quit();<br />
&nbsp;&nbsp;&nbsp;env</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">ReleaseStringUTFChars(pptFileName,ppt);<br />
&nbsp;&nbsp;&nbsp;env</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">ReleaseStringUTFChars(tmpDir,tmp);<br />
&nbsp;&nbsp;&nbsp;CoUninitialize();<br />
}</span></div>
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/172680.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-01-04 11:26 <a href="http://www.blogjava.net/killme2008/archive/2008/01/04/172680.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>视频站点的搭建</title><link>http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 19 Dec 2007 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/168788.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/168788.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/168788.html</trackback:ping><description><![CDATA[&nbsp; &nbsp; 挺久没动笔写blog了，换了新工作比较忙是一个原因。最近的工作是做一个素材管理的系统，其中有个要求做视频预览，将用户上传的视频转换并在网页上预览。在网页上看视频，现在大多数视频网站都是采用flv流媒体文件，用flash做的播放器播放，我们也采用了这种方式。流程大概主要：用户上传文件-&gt;后台转换文件成flv格式-&gt;flv播放器调用flv文件。<br />
&nbsp;&nbsp;&nbsp; 转换视频、音频文件到flv格式可以使用mencoder或者ffmpeg，我们采用了mencoder，在linux上的安装参考<a href="http://hi.baidu.com/flash%5Fzb/blog/item/bbf7668de6f85912b21bbae0.html">这里</a>,安装结束后记的设置环境变量：export LD_LIBRARY_PATH=/usr/local/lib:LD_LIBRARY_PATH<br />
&nbsp;&nbsp;&nbsp; java调用的话就是通过Process：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">&nbsp;Process&nbsp;process&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;runtime.exec(cmd);</span></div>
<br />
mencoder转换视频音频成flv命令：<br />
mencoder 源文件 -o 目标文件.flv -of lavf&nbsp;&nbsp;&nbsp; -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=400:mbd=2:mv0:trell:v4mv:cbp:last_pred=3:dia=4:cmp=6:vb_strategy=1 -vf scale=200:-3 -ofps 12 -srate 22050<br />
<br />
取视频元信息命令（视频比特率、长宽等信息）：<br />
mplayer -identify 文件名 -ao null -vo null -frames 0 <br />
<br />
切割视频命令：<br />
mencoder -ss 开始时间 -oac copy -ovc copy -endpos 终止时间 文件名 -o 目标文件名<br />
<br />
&nbsp;&nbsp;&nbsp; 操作flv文件（给视频打上信息、切割之类）可以采用<a href="http://rubyforge.org/projects/flvtool2/">flvtool2</a>。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 需要注意的是通过java调用的话，一定要处理标准输出和标准错误输出，不然进程会挂在那结束不了，可以开个线程取处理。在网页播放的话，可以考虑用<a href="http://hi.baidu.com/lzxinta/blog/item/4c02d55103216d2643a75b7b.html">这个播放器</a>，具体参数看它的说明。最后一个问题，IE6的flash控件需要激活，这个问题的解决可以采用<a href="http://blog.deconcept.com/swfobject/">swfobject.js</a>。<br />
&nbsp;&nbsp;&nbsp; 有兴趣的老大们可以考虑自己搭个&#8220;土豆网&#8221;，说不定哪天拿了风投.....浮云<br /><img src ="http://www.blogjava.net/killme2008/aggbug/168788.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-12-19 16:46 <a href="http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>抽取网页数据的不同思路</title><link>http://www.blogjava.net/killme2008/archive/2007/11/22/162338.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 22 Nov 2007 04:35:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/11/22/162338.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/162338.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/11/22/162338.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/162338.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/162338.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 客户要求从Internet上的网页上抽取一定的数据，用来显示或者其他用户，这个需求很常见。这两天我们也遇到了这个需求，本来我一开始想是试用正则表达式去匹配需要的文本数据，后来经验丰富的经理给出了一个更好的思路，就是使用<a>jtidy</a>将不符合xhtml的HTML文件转化成标准的xhtml文件——本质上就是XML文件，然后利用xsl抽取并转换成我们所需要的数据的一定格式的xml文件。这样做其实就是将XSL模板当正则表达式来用，不过更清晰，当网页改变时也不需要重新编译代码，仅仅修改XSL模板就够了。过程如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp; html-&gt;xhtml--xsl--&gt;数据xml<br />
<br />
&nbsp;&nbsp;&nbsp; 做的过程中，初次使用了xsl,xpath等技术，网上找了不少好资料，共享下：<br />
jtidy:&nbsp; <br />
<br />
思路来源<br />
http://www.ibm.com/developerworks/cn/xml/x-wbdm/<br />
<br />
项目地址<br />
http://jtidy.sourceforge.net/<br />
<br />
参考，解决中文问题使用<br />
http://www.blogjava.net/jhengfei/archive/2006/03/25/37312.html<br />
<br />
xsl,非常系统教程和实践:<br />
<br />
http://www.cnblogs.com/goody9807/category/36016.html<br />
<br />
xpath:<br />
<br />
http://www.yesky.com/201/171201.shtml<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/162338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-11-22 12:35 <a href="http://www.blogjava.net/killme2008/archive/2007/11/22/162338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再谈java的内存泄露</title><link>http://www.blogjava.net/killme2008/archive/2007/11/11/159786.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 11 Nov 2007 12:18:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/11/11/159786.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/159786.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/11/11/159786.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/159786.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/159786.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 这两天看了一本老书《bitter java》，第一次系统地了解了所谓&#8220;反模式&#8221;。就书的内容来说已经过于陈旧，书中提到的magic servlet、复合jsp等等反模式已经是早就熟知的编程禁忌，而如web页面不能有太多元素这样的反模式也因为ajax的出现（异步加载）变的不是那么&#8220;反模式&#8221;了，其中又讲述了很多ejb的反模式，这些在轻量级框架流行的今天也早已经过时。不过书中有一个章节倒是挺有价值，讲述的是java的内存泄露问题，我认为是我目前读的关于这方面问题比较有价值的介绍。<br />
&nbsp;&nbsp;&nbsp; 网上关于java内存泄露的资料都过于玄乎，其实java导致内存泄露的原因很明确：长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露，尽管短生命周期对象已经不再需要，但是因为长生命周期对象持有它的引用而导致不能被回收，这就是java中内存泄露的发生场景。作者在书中提到了3个场景：<br />
1。流失监听器问题，在awt、swing编程中，给组件添加了事件监听器，这些组件的生命周期如果很长的话，监听器对象将不能被正确回收。关于GUI编程我不是很熟悉，这一点存有疑问，因为显然你触发一个按钮的事件，当然是一直期待同样的行为发生，如果删除了监听器或者使用弱引用让JVM回收不符合业务逻辑和用户体验。<br />
<br />
2。集合类，集合类仅仅有添加元素的方法，而没有相应的删除机制，导致内存被占用。这一点其实也不明确，这个集合类如果仅仅是局部变量，根本不会造成内存泄露，在方法栈退出后就没有引用了会被jvm正常回收。而如果这个集合类是全局性的变量（比如类中的静态属性，全局性的map等），那么没有相应的删除机制，很可能导致集合所占用的内存只增不减，因此提供这样的删除机制或者定期清除策略非常必要。<br />
<br />
3。单例模式。不正确使用单例模式是引起内存泄露的一个常见问题，单例对象在被初始化后将在JVM的整个生命周期中存在（以静态变量的方式），如果单例对象持有外部对象的引用，那么这个外部对象将不能被jvm正常回收，导致内存泄露，考虑下面的例子：<br />
class A{<br />
&nbsp;&nbsp;&nbsp; public A(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B.getInstance().setA(this);<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; ....<br />
}<br />
//B类采用单例模式<br />
class B{<br />
&nbsp;&nbsp;&nbsp;&nbsp; private A a;<br />
&nbsp;&nbsp;&nbsp;&nbsp; private static B instance=new B();<br />
&nbsp;&nbsp;&nbsp;&nbsp; public B(){}<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static B getInstance(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return instance;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void setA(A a){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.a=a;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; //getter...<br />
}<br />
<br />
显然B采用singleton模式，他持有一个A对象的引用，而这个A类的对象将不能被回收。想象下如果A是个比较大的对象或者集合类型会发生什么情况。<br />
<br />
&nbsp;&nbsp;&nbsp; 上面所讲的这些也启发我们如何去查找内存泄露问题，第一选择当然是利用工具，比如jprofiler，第二就是在代码复审的时候关注长生命周期对象：全局性的集合、单例模式的使用、类的static变量等等。<br /><img src ="http://www.blogjava.net/killme2008/aggbug/159786.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-11-11 20:18 <a href="http://www.blogjava.net/killme2008/archive/2007/11/11/159786.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>写一个简单的工作流（四）资源的处理</title><link>http://www.blogjava.net/killme2008/archive/2007/10/13/152604.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 13 Oct 2007 09:15:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/10/13/152604.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/152604.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/10/13/152604.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/152604.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/152604.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 昨天晚上搞到深夜，终于将资源模块搞定。到今天已经完成的功能包括：<br />
1.四种基本路由：顺序、选择、并行、循环<br />
2.流程定义文件和系统配置文件的读取和解析<br />
3.使用内存作为流程数据和案例数据存储的MemoryWorkFlowDAO的开发<br />
4.资源模块的开发<br />
5.并发情况下的正确性测试等<br />
<br />
&nbsp;&nbsp;&nbsp; 计划中的功能：<br />
1.一个GUI的流程定义工具，这个不急，也还没想好用什么做，web还是桌面？<br />
2.各个数据库版本的WorkFlowDAO的开发，将流程数据和案例数据保存在数据库中。<br />
3.更多的测试和example试验。<br />
<br />
&nbsp;&nbsp;&nbsp; 回到资源这个概念，工作流中工作项（work item）的由资源来驱动的，这个资源(resource)可能是用户、角色、定时时间或者某个事件消息。在标准petri网中，工作项对应于transition(变迁），变迁都是自动的，不需要所谓资源来驱动，显然，这与工作流系统不同。具体到insect workflow(我取的名字，小巧之意），每个transition都有一个resource，用于驱动自身的firing，所有的resource都实现Resource接口：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;Resource&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;Serializable&nbsp;{<br />
<br />
&nbsp;&nbsp;&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;start(Transition&nbsp;transition,&nbsp;Token&nbsp;token,&nbsp;Object&nbsp;args);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ResourceType&nbsp;getType();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;getId();<br />
<br />
}</span></div>
&nbsp;&nbsp;&nbsp; 每个资源都有一个类型，以及这个类型中独一无二的id，start方法用于驱动transtion的firing。一般情况下，你不需要实现这个接口，只要继承这个接口的抽象实现类AbstractResource，AbstractResource的start方法默认实现是首先调用模板方法doAction（稍后解释）,然后检查触发条件，如果通过就直接调用transition的fire方法：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;AbstractResource&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Resource&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&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;start(Transition&nbsp;transition,&nbsp;Token&nbsp;token,&nbsp;Object&nbsp;args) </span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doAction(transition,&nbsp;token,&nbsp;args);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(transition.getCondition()&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;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">transition.getCondition().check(token))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ConditionException(transition.getName()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;transition没有满足触发条件</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transition.fire(token,&nbsp;args);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;doAction(Transition&nbsp;transition,&nbsp;Token&nbsp;token,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object<img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;args) </span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
}</span></div>
<br />
&nbsp;&nbsp;&nbsp; Transtion类的fire方法有三个操作组成：从输入库所移走token，往输出库所放入token，回调handler：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;fire(Token&nbsp;token,&nbsp;Object<img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;removeTokenFromInputs(token);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addTokenToOutputs(token);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invokeHandler(token,&nbsp;args);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
&nbsp;&nbsp;&nbsp; 那么具体的资源显然要实现AbstractResource中的doAction抽象方法，系统内置了五种资源：自动资源（AutoResource）、用户(User)、用户组(Group)、定时器(TimerResource)和事件监听器（ObserverResource）。显然，AutoResource、User和Group的doAction方法不需要做任何事情：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;User&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;AbstractResource&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;Group&nbsp;group;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&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;doAction(Transition&nbsp;transition,&nbsp;Token&nbsp;token,&nbsp;Object<img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;arg)</span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</span></div>
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 而TimerResource就需要做特殊处理了，比如我们要达到这样的效果：节点1状态已经处于就绪，可以被触发，可我们希望在就绪后延迟半分钟再触发，或者在晚上10点触发等等。这样的定时需求很常见，我采用了jdk5引入的ScheduledExecutorService来处理。系统中启动这样一个线程池，每个类似上面的请求都提交给这个线程池来处理，那么TimerResource就需要进行相应的修改：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;TimerResource&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;AbstractResource&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;pool_size;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;ScheduledExecutorService&nbsp;scheduledExecutorService;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;getId()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;Common.TIMER_RESOURCE_ID;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;TimerResource()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.pool_size&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scheduledExecutorService&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Executors.newScheduledThreadPool(pool_size);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;shutdownPool()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(scheduledExecutorService&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;scheduledExecutorService.shutdown();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;start(Transition&nbsp;transition,&nbsp;Token&nbsp;token,&nbsp;Object<img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;args)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;InterruptedException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(transition.getCondition()&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;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">transition.getCondition().check(token))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ConditionException(transition.getName()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;transition没有满足触发条件</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transition.removeTokenFromInputs(token);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doAction(transition,&nbsp;token,&nbsp;args);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ChangeRunner&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Runnable&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Transition&nbsp;transition;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Token&nbsp;token;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;Object[]&nbsp;args;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ChangeRunner(Transition&nbsp;transition,&nbsp;Token&nbsp;token,&nbsp;Object<img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.transition&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;transition;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.token&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;token;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.args&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;args;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;run()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(transition.getCondition()&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;&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">transition.getCondition().check(token))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ConditionException(transition.getName()<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;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;transition没有满足触发条件</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transition.addTokenToOutputs(token);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;real_args[]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Object[args.length&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;real_args.length;&nbsp;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;real_args[i]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;args[i&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transition.invokeHandler(token,&nbsp;real_args);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&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;">&nbsp;回调</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((WorkFlowAlgorithm)&nbsp;args[</span><span style="color: #000000;">1</span><span style="color: #000000;">]).enabledTraversing(token<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;.getWorkFlow());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((WorkFlowManager)&nbsp;args[</span><span style="color: #000000;">0</span><span style="color: #000000;">]).doAction(token.getId());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(InterruptedException&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.currentThread().interrupt();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
&nbsp;&nbsp;&nbsp; 注意到，start方法不再是直接调用transition的fire方法，而仅仅是进行了第一步操作：移除输入库所的place防止重复提交。后两步操作都延迟到了提交给线程池的任务中，也就是代码中的<span style="color: #000000;">ChangeRunner类中的run方法。例如TimerResource的子类DelayTimerResource用于处理延迟的触发，doAction就像这样：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;DelayTimerResource&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;TimerResource&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&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;doAction(Transition&nbsp;transition,&nbsp;Token&nbsp;token,&nbsp;Object<img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;args)</span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scheduledExecutorService.schedule(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ChangeRunner(transition,&nbsp;token,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args),&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.delay,&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.timeUnit);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
&nbsp;&nbsp;&nbsp; 延迟的时间，时间单位这些信息都可以在流程定义文件中设置。事件监听器资源与此类似，ObserverResource实现了java.util.Observer接口，往输出库所放入token和回调handler两步操作被放在了update方法中提供给Subject回调。<br />
&nbsp;&nbsp;&nbsp; <br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/152604.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-10-13 17:15 <a href="http://www.blogjava.net/killme2008/archive/2007/10/13/152604.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>写一个简单的工作流（二）</title><link>http://www.blogjava.net/killme2008/archive/2007/10/11/152093.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 11 Oct 2007 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/10/11/152093.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/152093.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/10/11/152093.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/152093.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/152093.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; hoho，今天完成了选择路由的实现，完成了配置文件的读写和解析，流程定义文件还是决定采用xml文件，不过与其他工作流引擎采用的xml完全不同，因为是基于petri网的，因此引入了place的概念，比如下面这个4个节点的顺序路由的流程：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">workflow&nbsp;</span><span style="color: #ff0000;">maxCases</span><span style="color: #0000ff;">="100"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">node&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="start"</span><span style="color: #ff0000;">&nbsp;name</span><span style="color: #0000ff;">="start"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="0"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="1"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="2"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">node</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">node&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="hello"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="1"</span><span style="color: #ff0000;">&nbsp;resource</span><span style="color: #0000ff;">="user"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">conditions&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="and"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">condition<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="net.rubyeye.insect.workflow.impl.NullHandler"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="false"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;variable-name</span><span style="color: #0000ff;">="name"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">conditions</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">handler<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="net.rubyeye.insect.workflow.test.HelloWorldHandler"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="2"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="3"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">node</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">node&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="calc"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="2"</span><span style="color: #ff0000;">&nbsp;resource</span><span style="color: #0000ff;">="user"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">conditions&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="and"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">condition&nbsp;</span><span style="color: #ff0000;">variable-name</span><span style="color: #0000ff;">="num"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">exp</span><span style="color: #0000ff;">&gt;</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;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">num&lt;=1000</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">exp</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">condition</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">conditions&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="or"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">condition&nbsp;</span><span style="color: #ff0000;">variable-name</span><span style="color: #0000ff;">="num"</span><span style="color: #0000ff;">&gt;</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;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">exp</span><span style="color: #0000ff;">&gt;</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;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">num&gt;=10</span><span style="color: #0000ff;">]]&gt;</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;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">exp</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">condition</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">condition<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="net.rubyeye.insect.workflow.impl.NullHandler"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="false"</span><span style="color: #ff0000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;variable-name</span><span style="color: #0000ff;">="name"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">conditions</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">conditions</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">handler<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000;">class</span><span style="color: #0000ff;">="net.rubyeye.insect.workflow.test.CalculateHandler"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="3"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="4"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">node</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">node&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="end"</span><span style="color: #ff0000;">&nbsp;name</span><span style="color: #0000ff;">="hello"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="3"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="4"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="5"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">node</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">workflow</span><span style="color: #0000ff;">&gt;</span></div>
&nbsp;&nbsp;&nbsp; <br />
并行路由和选择路由引入了and-split,and-join,or-split,or-join四种transition，比如and-split，它就有多个输出place：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">node&nbsp;</span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="split"</span><span style="color: #ff0000;">&nbsp;type</span><span style="color: #0000ff;">="and-split"</span><span style="color: #ff0000;">&nbsp;id</span><span style="color: #0000ff;">="1"</span><span style="color: #ff0000;">&nbsp;resource</span><span style="color: #0000ff;">="user"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="2"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">inputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="3"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">place&nbsp;</span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="4"</span><span style="color: #ff0000;">&nbsp;</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">outputs</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">node</span><span style="color: #0000ff;">&gt;</span></div>
<br />
&nbsp;&nbsp; Place和Transition都有条件，用于决定操作是否执行，Transition额外指定了驱动的资源以及回调的handler，这一点非常重要，资源可能是用户、用户组、某个时间点定时事件、特定消息等等。<br />
&nbsp;&nbsp; 今天额外发现的一个好处就是，引入Place之后，我可以轻易地将不同的流程连接起来组织成一个更复杂的流程，仅仅是需要修改各个流程的开始和结束的节点的输入输出库所,从而实现了层次化的Petri网,，类似代码：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">WorkFlow&nbsp;sequence&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;wm.getWorkFlow(</span><span style="color: #000000;">"</span><span style="color: #000000;">sequence</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WorkFlow&nbsp;concurrency&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;wm.getWorkFlow(</span><span style="color: #000000;">"</span><span style="color: #000000;">concurrency</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WorkFlow&nbsp;choose&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;wm.getWorkFlow(</span><span style="color: #000000;">"</span><span style="color: #000000;">choose</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">组合流程</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;composite&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;WorkFlow();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;composite.setName(</span><span style="color: #000000;">"</span><span style="color: #000000;">composite</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;composite.setId(</span><span style="color: #000000;">100</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wm.saveWorkFlow(composite);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">修改开始结束节点的输入输出库所</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sequence.getEnd().setType(TransitionType.NORMAL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sequence.getEnd().setOutputs(concurrency.getStart().getInputs());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;concurrency.getEnd().setType(TransitionType.NORMAL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;concurrency.getEnd().setOutputs(choose.getStart().getInputs());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;composite.setStart(sequence.getStart());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;composite.setEnd(choose.getEnd());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Transition</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;transitions&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Transition</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transitions.addAll(sequence.getTransitions());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transitions.addAll(concurrency.getTransitions());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;transitions.addAll(choose.getTransitions());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;composite.setTransitions(transitions);</span></div>
<br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/152093.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-10-11 16:51 <a href="http://www.blogjava.net/killme2008/archive/2007/10/11/152093.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>写一个简单的工作流，基于petri网</title><link>http://www.blogjava.net/killme2008/archive/2007/10/10/151845.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 10 Oct 2007 10:03:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/10/10/151845.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/151845.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/10/10/151845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/151845.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/151845.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 写一个简单的工作流一直停留在我的&#8220;计划&#8221;中，最近趁改造绩效系统的机会，决定自己写一个基于petri网原理的工作流来改写绩效考核流程部分。基于petri网的工作流的基本算法，就是当每一个firing发生后，应当遍历整个流程重新改变transition的enable，那么当资源驱动某个transition其实就是将它的输入place中的token转移到输出place。大概的接口类似：<br />
<br />
WorkFlowManager wm = new BasicWorkflowManager(this.workFlowDAO);<br />
Token token1 = wm.startWorkFlow(0); //为流程0新启动一个案例<br />
wm.doAction(token1,resource,args);&nbsp; //传入资源和参数以驱动firing<br />
<br />
今天完成了顺序路由和并行路由的实现，选择和循环也准备加入。暂时只实现了内存存储案例数据和流程数据，显然，应当实现一个数据库版本，慢慢来吧。<img src ="http://www.blogjava.net/killme2008/aggbug/151845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-10-10 18:03 <a href="http://www.blogjava.net/killme2008/archive/2007/10/10/151845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单LRU算法实现缓存-update2</title><link>http://www.blogjava.net/killme2008/archive/2007/09/29/149645.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 29 Sep 2007 09:49:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/29/149645.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/149645.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/29/149645.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/149645.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/149645.html</trackback:ping><description><![CDATA[update1:第二个实现，读操作不必要采用独占锁，缓存显然是读多于写，读的时候一开始用独占锁是考虑到要递增计数和更新时间戳要加锁，不过这两个变量都是采用原子变量，因此也不必采用独占锁，修改为读写锁。<br />
update2:一个错误，老是写错关键字啊，<span style="color: #000000;">LRUCache的</span><span style="color: #000000;">maxCapacity应该声明为volatile，而不是transient。</span><br />
&nbsp;&nbsp;  <br />
&nbsp;&nbsp; 最简单的LRU算法实现，就是利用jdk的LinkedHashMap，覆写其中的removeEldestEntry(Map.Entry)方法即可，如下所示：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.ArrayList;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.Collection;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.LinkedHashMap;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.locks.Lock;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.locks.ReentrantLock;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.Map;<br />
<br />
<br />
</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;类说明：利用LinkedHashMap实现简单的缓存，&nbsp;必须实现removeEldestEntry方法，具体参见JDK文档<br />
&nbsp;*&nbsp;<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;dennis<br />
&nbsp;*&nbsp;<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;&lt;K&gt;<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;&lt;V&gt;<br />
&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;LRULinkedHashMap</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;LinkedHashMap</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;maxCapacity;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">float</span><span style="color: #000000;">&nbsp;DEFAULT_LOAD_FACTOR&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0.75f</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Lock&nbsp;lock&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ReentrantLock();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;LRULinkedHashMap(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;maxCapacity)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">(maxCapacity,&nbsp;DEFAULT_LOAD_FACTOR,&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.maxCapacity&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;maxCapacity;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;removeEldestEntry(java.util.Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;eldest)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;size()&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;maxCapacity;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;containsKey(Object&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock();<br />
&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;">super</span><span style="color: #000000;">.containsKey(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;V&nbsp;get(Object&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock();<br />
&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;">super</span><span style="color: #000000;">.get(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;V&nbsp;put(K&nbsp;key,&nbsp;V&nbsp;value)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock();<br />
&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;">super</span><span style="color: #000000;">.put(key,&nbsp;value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;size()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock();<br />
&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;">super</span><span style="color: #000000;">.size();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;clear()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">.clear();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Collection</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">&nbsp;getAll()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock();<br />
&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;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">(</span><span style="color: #0000ff;">super</span><span style="color: #000000;">.entrySet());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
&nbsp;&nbsp;&nbsp; 如果你去看LinkedHashMap的源码可知，LRU算法是通过双向链表来实现，当某个位置被命中，通过调整链表的指向将该位置调整到头位置，新加入的内容直接放在链表头，如此一来，最近被命中的内容就向链表头移动，需要替换时，链表最后的位置就是最近最少使用的位置。<br />
&nbsp;&nbsp;&nbsp; LRU算法还可以通过计数来实现，缓存存储的位置附带一个计数器，当命中时将计数器加1，替换时就查找计数最小的位置并替换，结合访问时间戳来实现。这种算法比较适合缓存数据量较小的场景，显然，遍历查找计数最小位置的时间复杂度为O(n)。我实现了一个，结合了访问时间戳，当最小计数大于MINI_ACESS时(这个参数的调整对命中率有较大影响），就移除最久没有被访问的项：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;net.rubyeye.codelib.util.concurrency.cache;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.Serializable;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.ArrayList;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.Collection;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.HashMap;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.Iterator;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.Map;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.Set;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.atomic.AtomicInteger;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.atomic.AtomicLong;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.locks.Lock;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.locks.ReadWriteLock;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.locks.ReentrantLock;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.locks.ReentrantReadWriteLock;<br />
<br />
</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;dennis&nbsp;类说明：当缓存数目不多时，才用缓存计数的传统LRU算法<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;&lt;K&gt;<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;&lt;V&gt;<br />
&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;LRUCache</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Serializable&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;DEFAULT_CAPACITY&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">100</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;Map</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;ValueEntry</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;map;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ReadWriteLock&nbsp;lock&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ReentrantReadWriteLock();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Lock&nbsp;readLock&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;lock.readLock();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Lock&nbsp;writeLock&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;lock.writeLock();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;"> </span><span style="color: #0000ff;">volatile</span><span style="color: #000000;"> </span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;maxCapacity;&nbsp; //保持可见性<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;MINI_ACCESS&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;LRUCache()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">(DEFAULT_CAPACITY);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;LRUCache(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;capacity)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(capacity&nbsp;</span><span style="color: #000000;">&lt;=</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;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;RuntimeException(</span><span style="color: #000000;">"</span><span style="color: #000000;">缓存容量不得小于0</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.maxCapacity&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;capacity;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.map&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;HashMap</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;ValueEntry</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(maxCapacity);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;ContainsKey(K&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&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;">.map.containsKey(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;V&nbsp;put(K&nbsp;key,&nbsp;V&nbsp;value)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((map.size()&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;maxCapacity&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">map.containsKey(key))&nbsp;{<br />
&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;">&nbsp;System.out.println("开始");</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;ValueEntry</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">&nbsp;entries&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.map.entrySet();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;removeRencentlyLeastAccess(entries);<br />
&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;ValueEntry&nbsp;new_value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ValueEntry(value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ValueEntry&nbsp;old_value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;map.put(key,&nbsp;new_value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(old_value&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new_value.count&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;old_value.count;<br />
&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;old_value.value;<br />
&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;</span><span style="color: #0000ff;">return</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;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;移除最近最少访问<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;removeRencentlyLeastAccess(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;ValueEntry</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">&nbsp;entries)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;最小使用次数</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;least&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;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;访问时间最早</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;earliest&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;K&nbsp;toBeRemovedByCount&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;K&nbsp;toBeRemovedByTime&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;Iterator</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;ValueEntry</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">&nbsp;it&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;entries.iterator();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(it.hasNext())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;ValueEntry</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;valueEntry&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;it.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;least&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;valueEntry.getValue().count.get();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toBeRemovedByCount&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;valueEntry.getKey();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;earliest&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;valueEntry.getValue().lastAccess.get();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toBeRemovedByTime&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;valueEntry.getKey();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(it.hasNext())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;ValueEntry</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;valueEntry&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;it.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(valueEntry.getValue().count.get()&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;least)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;least&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;valueEntry.getValue().count.get();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toBeRemovedByCount&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;valueEntry.getKey();<br />
&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;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(valueEntry.getValue().lastAccess.get()&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;earliest)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;earliest&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;valueEntry.getValue().count.get();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;toBeRemovedByTime&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;valueEntry.getKey();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;System.out.println("remove:"&nbsp;+&nbsp;toBeRemoved);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;如果最少使用次数大于MINI_ACCESS，那么移除访问时间最早的项(也就是最久没有被访问的项）</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(least&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;MINI_ACCESS)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.remove(toBeRemovedByTime);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.remove(toBeRemovedByCount);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;V&nbsp;get(K&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;value&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;ValueEntry&nbsp;valueEntry&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;map.get(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(valueEntry&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&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;">&nbsp;更新访问时间戳</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;valueEntry.updateLastAccess();<br />
&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;">&nbsp;更新访问次数</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;valueEntry.count.incrementAndGet();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;valueEntry.value;<br />
&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;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;clear()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.clear();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;size()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;map.size();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;getCount(K&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ValueEntry&nbsp;valueEntry&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;map.get(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(valueEntry&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
&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;valueEntry.count.get();<br />
&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;</span><span style="color: #0000ff;">return</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;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Collection</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">&nbsp;getAll()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;keys&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;map.keySet();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;tmp&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;HashMap</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(K&nbsp;key&nbsp;:&nbsp;keys)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp.put(key,&nbsp;map.get(key).value);<br />
&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;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Map.Entry</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">K,&nbsp;V</span><span style="color: #000000;">&gt;&gt;</span><span style="color: #000000;">(tmp.entrySet());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ValueEntry&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Serializable&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;V&nbsp;value;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;AtomicLong&nbsp;count;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;AtomicLong&nbsp;lastAccess;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ValueEntry(V&nbsp;value)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.value&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.count&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;AtomicLong(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastAccess&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;AtomicLong(System.nanoTime());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;updateLastAccess()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.lastAccess.set(System.nanoTime());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span></div>
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--></div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/149645.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-29 17:49 <a href="http://www.blogjava.net/killme2008/archive/2007/09/29/149645.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ReentrantLock和内部锁的性能对比（update)</title><link>http://www.blogjava.net/killme2008/archive/2007/09/14/145195.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 14 Sep 2007 09:15:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/14/145195.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/145195.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/14/145195.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/145195.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/145195.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; ReentrantLock是jdk5引入的新的锁机制，它与内部锁（synchronize） 相同的并发性和内存语义，比如可重入加锁语义。在中等或者更高负荷下，ReentrantLock有更好的性能，并且拥有可轮询和可定时的请求锁等高级功能。这个程序简单对比了ReentrantLock公平锁、ReentrantLock非公平锁以及内部锁的性能，从结果上看，非公平的ReentrantLock表现最好。内部锁也仅仅是实现统计意义上的公平，结果也比公平的ReentrantLock好上很多。这个程序仅仅是计数，启动N个线程，对同一个Counter进行递增，显然，这个递增操作需要同步以保证原子性，采用不同的锁来实现同步，然后查看结果。<br />
Counter接口：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);">&nbsp;net.rubyeye.concurrency.chapter13;<br />
<br />
</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">interface</span><span style="color: rgb(0, 0, 0);">&nbsp;Counter&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">long</span><span style="color: rgb(0, 0, 0);">&nbsp;getValue();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;increment();<br />
<br />
}<br />
</span></div>
<br />
然后，首先使用我们熟悉的synchronize来实现同步：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);">&nbsp;net.rubyeye.concurrency.chapter13;<br />
<br />
</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;SynchronizeBenchmark&nbsp;</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;Counter&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">long</span><span style="color: rgb(0, 0, 0);">&nbsp;count&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">long</span><span style="color: rgb(0, 0, 0);">&nbsp;getValue()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;count;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">synchronized</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;increment()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span></div>
<br />
采用ReentrantLock的版本，切记要在finally中释放锁，这是与synchronize使用方式最大的不同，内部锁jvm会自动帮你释放锁，而ReentrantLock需要你自己来处理。<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);">&nbsp;net.rubyeye.concurrency.chapter13;<br />
<br />
</span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;java.util.concurrent.locks.Lock;<br />
</span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;java.util.concurrent.locks.ReentrantLock;<br />
<br />
</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;ReentrantLockBeanchmark&nbsp;</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;Counter&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">volatile</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">long</span><span style="color: rgb(0, 0, 0);">&nbsp;count&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;Lock&nbsp;lock;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;ReentrantLockBeanchmark()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;使用非公平锁，true就是公平锁</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;ReentrantLock(</span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">long</span><span style="color: rgb(0, 0, 0);">&nbsp;getValue()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;count;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;increment()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}<br />
</span></div>
<br />
&nbsp;&nbsp;&nbsp; 写一个测试程序，使用CyclicBarrier来等待所有任务线程创建完毕以及所有任务线程计算完成，清单如下：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);">&nbsp;net.rubyeye.concurrency.chapter13;<br />
<br />
</span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;java.util.concurrent.CyclicBarrier;<br />
<br />
</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;BenchmarkTest&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;Counter&nbsp;counter;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;CyclicBarrier&nbsp;barrier;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;threadNum;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;BenchmarkTest(Counter&nbsp;counter,&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;threadNum)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.counter&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;counter;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;barrier&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;CyclicBarrier(threadNum&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">);&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">关卡计数=线程数+1</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.threadNum&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;threadNum;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;main(String&nbsp;args[])&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;BenchmarkTest(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;SynchronizeBenchmark(),&nbsp;</span><span style="color: rgb(0, 0, 0);">5000</span><span style="color: rgb(0, 0, 0);">).test();<br />
&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">new&nbsp;BenchmarkTest(new&nbsp;ReentrantLockBeanchmark(),&nbsp;5000).test();<br />
</span><span style="color: rgb(0, 128, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span style="color: rgb(0, 128, 0);">new&nbsp;BenchmarkTest(new&nbsp;ReentrantLockBeanchmark(),&nbsp;5000).test();&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;test()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;threadNum;&nbsp;i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;TestThread(counter).start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="color: rgb(0, 0, 255);">long</span><span style="color: rgb(0, 0, 0);">&nbsp;start&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;System.currentTimeMillis();</span><br />
<span style="color: rgb(0, 0, 0);">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; barrier.await();&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;等待所有任务线程创建</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 0);"> barrier.await();&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;等待所有任务计算完成</span><span style="color: rgb(0, 128, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">long</span><span style="color: rgb(0, 0, 0);">&nbsp;end&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;System.currentTimeMillis();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">count&nbsp;value:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;counter.getValue());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">花费时间:</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;(end&nbsp;</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">&nbsp;start)&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">毫秒</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">&nbsp;(Exception&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;RuntimeException(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;TestThread&nbsp;</span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);">&nbsp;Thread&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">&nbsp;Counter&nbsp;counter;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;TestThread(</span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);">&nbsp;Counter&nbsp;counter)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.counter&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;counter;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;run()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;barrier.await();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">;&nbsp;i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;counter.increment();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;barrier.await();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">&nbsp;(Exception&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;RuntimeException(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
分别测试一下，<br />
<br />
将启动的线程数限定为500，结果为：<br />
公平ReentrantLock:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 210 毫秒<br />
非公平ReentrantLock :&nbsp;&nbsp; 39&nbsp; 毫秒<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; 39 毫秒<br />
<br />
将启动的线程数限定为1000，结果为：<br />
公平ReentrantLock:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 640 毫秒<br />
非公平ReentrantLock :&nbsp;&nbsp; 81 毫秒<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; 60 毫秒<br />
<br />
线程数不变，test方法中的循环增加到1000次，结果为：<br />
公平ReentrantLock:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16715 毫秒<br />
非公平ReentrantLock :&nbsp;&nbsp; 168 毫秒<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; 639&nbsp; 毫秒<br />
<br />
将启动的线程数增加到2000,结果为：<br />
公平ReentrantLock:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1100 毫秒<br />
非公平ReentrantLock:&nbsp;&nbsp; 125 毫秒<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; 130 毫秒<br />
<br />
将启动的线程数增加到3000,结果为：<br />
公平ReentrantLock:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2461 毫秒<br />
非公平ReentrantLock:&nbsp;&nbsp; 254 毫秒<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; 307 毫秒<br />
<br />
启动5000个线程，结果如下：<br />
公平ReentrantLock:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6154&nbsp; 毫秒<br />
非公平ReentrantLock:&nbsp;&nbsp; 623 &nbsp; 毫秒<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; 720 毫秒<br />
<br />
非公平ReentrantLock和内部锁的差距，在jdk6上应该缩小了，据说jdk6的内部锁机制进行了调整。<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--></div><img src ="http://www.blogjava.net/killme2008/aggbug/145195.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-14 17:15 <a href="http://www.blogjava.net/killme2008/archive/2007/09/14/145195.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Doug Lea的并发包实现带超时机制的线程池</title><link>http://www.blogjava.net/killme2008/archive/2007/09/09/143777.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 09 Sep 2007 06:23:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/09/143777.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/143777.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/09/143777.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/143777.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/143777.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; jdk5引入的concurrent包来自于Doug Lea的卓越贡献。最近我在查找服务器OOM的原因之后，决定采用这个包重写应用中一个servlet，这个servlet调用了一个阻塞方法，当被阻塞之后，服务器中的线程数（因为阻塞了，后续请求不断地新增线程）突然增加导致了服务器当机，因此决定采用一个线程池，并且设置超时，如果阻塞方法超过一定时间就取消线程。因为我们的项目仍然跑在jdk 1.4.2上面，短期内不可能升级到jdk5，还是要利用这个并发包。去<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html">这里</a>下载源码并自己打包成jar，加入项目的lib，然后利用<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/PooledExecutor.html">PooledExecutor</a>和<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/TimedCallable.html">TimedCallable</a>来实现我们的需求。首先是线程池，相当简单：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;EDU.oswego.cs.dl.util.concurrent.PooledExecutor;<br />
</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;&lt;p&gt;类说明：线程池&lt;/p&gt;<br />
&nbsp;*&nbsp;&lt;p&gt;注意事项：&lt;/p&gt;<br />
&nbsp;*&nbsp;&lt;pre&gt;&lt;/pre&gt;<br />
&nbsp;*&nbsp;&lt;p&gt;创建日期：Sep&nbsp;7,&nbsp;2007&nbsp;1:25:33&nbsp;PM&lt;/p&gt;<br />
*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">:dennis&nbsp;zane<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@version</span><span style="color: #008000;">&nbsp;$Id:$<br />
&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;MyThreadPool{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;PooledExecutor&nbsp;exec&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;PooledExecutor(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;BoundedBuffer(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">20</span><span style="color: #000000;">),&nbsp;</span><span style="color: #000000;">30</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec.setKeepAliveTime(</span><span style="color: #000000;">1000</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">60</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec.createThreads(</span><span style="color: #000000;">5</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec.setMinimumPoolSize(</span><span style="color: #000000;">4</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;execute(</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Runnable&nbsp;r)&nbsp;</span> throws InterruptedException<span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp; exec.execute(r);<br />
&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;shutdown()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec.shutdownAfterProcessingCurrentlyQueuedTasks();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec&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;}<br />
<br />
}<br />
<br />
</span></div>
<br />
&nbsp;&nbsp;&nbsp; 静态初始化并设置一个PoolExecutor，设置空闲线程的存活时间为5分钟，设置最小线程数为4，最大线程数为30,一开始创建5个线程以待使用（根据各自的应用调整这些参数），另外提供了shutdown方法以供ServeltContextListener的contextDestroyed方法调用以关闭线程池。那么，结合TimedCallable来实现提交线程的超时机制,调用类似：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </span>//设置超时时间<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; private static final long timeout = 1000;<br />
&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; try{<br />
<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Callable&nbsp;callable&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Callable()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Object&nbsp;call()&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: #000000;">return new YourProgram().run(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;"><br />
&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;};<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TimedCallable&nbsp;timedCallable&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;TimedCallable(callable,&nbsp;timeout);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FutureResult&nbsp;future&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;FutureResult();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runnable&nbsp;cmd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;future.setter(timedCallable);<br />
&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: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyThreadPool.execute(cmd);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //获取任务结果 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; YourObject obj</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(YourObject)&nbsp;future.get();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span> catch (InterruptedException e) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (e instanceof TimeoutException) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log.error("任务超时");<br />
&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; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(InvocationTargetException e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //清理任务..<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br />
</div>
如果不是很理解这段代码，那么也许你应该先看看jdk5引入的Future、FutureTask等类，或者看看<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html">这里</a>的文档。对于超时时间的大小估算，你应当在生产环境中计算该阻塞方法的调用时间，正常运行一段时间，利用脚本语言（比如ruby、python）分析日志以得到一个调用花费时间的最大值作为timeout，这里的单位是毫秒。而线程池大小的估算，要看你提交给线程执行的任务的类型：如果是计算密集型的任务，那么线程池的大小一般是（cpu个数+1）；如果是IO密集型的任务（一般的web应用皆是此类），那么估算有一个公式,<br />
假设N-cpu是cpu个数，U是目标CPU使用率，W/C是任务的等待时间与计算时间的比率，那么最优的池大小等于：<br />
N-threads=N-cpu*U*(1+W/C)<br />
&nbsp;&nbsp;&nbsp; <br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/143777.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-09 14:23 <a href="http://www.blogjava.net/killme2008/archive/2007/09/09/143777.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PIPE2——Petri网编辑工具</title><link>http://www.blogjava.net/killme2008/archive/2007/09/05/142936.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 05 Sep 2007 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/05/142936.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/142936.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/05/142936.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/142936.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/142936.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 最近重新拿起《工作流管理-模型、方法和系统》，需要一个Petri网画图、分析的工具，google一把，在sourceforge上找到PIPE2项目。按它的描述是：Platform Independent Petri Net Editor 2。看了下源码是用swing写的。已经基本满足我的要求了。<br />
项目地址：http://pipe2.sourceforge.net/<br />
<br />
下图是对书中习题七的过程定义<br />
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/ex7.PNG" alt="" border="0" /><br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/142936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-05 16:51 <a href="http://www.blogjava.net/killme2008/archive/2007/09/05/142936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>线程任务的取消 </title><link>http://www.blogjava.net/killme2008/archive/2007/09/03/142344.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 03 Sep 2007 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/03/142344.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/142344.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/03/142344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/142344.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/142344.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 当外部代码能够在活动自然完成之前，把它的状态更改为完成状态，那么这个活动被称为可取消（cancellable）。取消任务是一个很常见的需求，无论是由于用户请求还是系统错误引起的服务关闭等等原因。最简单的任务取消策略就是在线程中维持一个bool变量，在run方法中判断此变量的bool值来决定是否取消任务。显然，这个bool变量需要声明为volatile，以保持多线程环境下可见性（所谓可见性，就是当一个线程修改共享对象的某个状态变量后，另一个线程可以马上看到修改结果）。下面是一个来自《java并发编程实践》的例子：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;net.rubyeye.concurrency.chapter7;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.math.BigInteger;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.ArrayList;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.List;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.TimeUnit;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;PrimeGenerator&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Runnable&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;primes&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">volatile</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;cancelled;<br />
&nbsp;&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;run()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigInteger&nbsp;p&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;BigInteger.ONE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">cancelled)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;p.nextProbablePrime();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primes.add(p);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&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;cancel()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cancelled&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;}<br />
&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;">&nbsp;List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;get()&nbsp;{<br />
&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;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(primes);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String&nbsp;args[])&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;InterruptedException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrimeGenerator&nbsp;generator&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;PrimeGenerator();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Thread(generator).start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TimeUnit.SECONDS.sleep(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generator.cancel();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span></div>
&nbsp;&nbsp;&nbsp; main中启动一个素数生成的任务，线程运行一秒就取消掉。通过线程中的cancelled变量来表征任务是否继续执行。既然是最简单的策略，那么什么是例外情况？显然，阻塞操作下（比如调用join,wait,sleep方法)，这样的策略会出问题。任务因为调用这些阻塞方法而被阻塞，它将不会去检查volatile变量，导致取消操作失效。那么解决办法是什么？中断！考虑我们用BlockingQueue去保存生成的素数，BlockingQueue的put方法是阻塞的（当BlockingQueue满的时候，put操作会阻塞直到有元素被take），让我们看看不采用中断，仍然采用简单策略会出现什么情况：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;net.rubyeye.concurrency.chapter7;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.math.BigInteger;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.BlockingQueue;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.CountDownLatch;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.LinkedBlockingQueue;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.TimeUnit;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;BrokenPrimeProducer&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;Thread&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;BlockingQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;queue;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">volatile</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;cancelled&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;BrokenPrimeProducer(BlockingQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;queue)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.queue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;queue;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;run()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigInteger&nbsp;p&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;BigInteger.ONE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">cancelled)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;p.nextProbablePrime();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;queue.put(p);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(InterruptedException&nbsp;cusumed)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;cancel()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.cancelled&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String&nbsp;args[])&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;InterruptedException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BlockingQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;queue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;LinkedBlockingQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BrokenPrimeProducer&nbsp;producer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;BrokenPrimeProducer(queue);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;producer.start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(needMorePrimes())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;queue.take();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;producer.cancel();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;needMorePrimes()&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;InterruptedException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;result&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;i</span><span style="color: #000000;">--</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(i&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;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;result;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span></div>
&nbsp;&nbsp;&nbsp; 我们在main中通过queue.take来消费产生的素数（虽然仅仅是取出扔掉），我们只消费了1000个素数，然后尝试取消产生素数的任务，很遗憾，取消不了，因为产生素数的线程产生素数的速度大于我们消费的速度，我们在消费1000后就停止消费了，那么任务将被queue的put方法阻塞，永远也不会去判断cancelled状态变量，任务取消不了。正确的做法应当是使用中断(interrupt）：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;net.rubyeye.concurrency.chapter7;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.math.BigInteger;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.BlockingQueue;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.CountDownLatch;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.LinkedBlockingQueue;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.concurrent.TimeUnit;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;PrimeProducer&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;Thread&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;BlockingQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;queue;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">volatile</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;cancelled&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;PrimeProducer(BlockingQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;queue)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.queue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;queue;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;run()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BigInteger&nbsp;p&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;BigInteger.ONE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">Thread.currentThread().isInterrupted())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;p.nextProbablePrime();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;queue.put(p);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(InterruptedException&nbsp;cusumed)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;cancel()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interrupt();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String&nbsp;args[])&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;InterruptedException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BlockingQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;queue&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;LinkedBlockingQueue</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BigInteger</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrimeProducer&nbsp;producer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;PrimeProducer(queue);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;producer.start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(needMorePrimes())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;queue.take();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;producer.cancel();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;needMorePrimes()&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;InterruptedException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">boolean</span><span style="color: #000000;">&nbsp;result&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;i</span><span style="color: #000000;">--</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(i&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;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;result;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</span></div>
&nbsp;&nbsp; 在run方法中，通过Thread的isInterrupted来判断interrupt status是否已经被修改，从而正确实现了任务的取消。关于interrupt，有一点需要特别说明，调用interrupt并不意味着必然停止目标线程的正在进行的工作，它仅仅是传递一个请求中断的信号给目标线程，目标线程会在下一个方便的时刻中断。而对于阻塞方法产生的InterruptedException的处理，两种选择：要么重新抛出让上层代码来处理，要么在catch块中调用Thread的interrupt来保存中断状态。除非你确定要让工作线程终止（如上所示代码），否则不要仅仅是catch而不做任务处理工作（生吞了InterruptedException)，更详细可以参考<a href="http://www.ibm.com/developerworks/cn/java/j-jtp05236.html">这里</a>。如果不清楚外部线程的中断策略，生搬硬套地调用<em>interrupt</em>可能产生不可预料的后果，可参见书中7.1.4例子。<br />
<br />
&nbsp;&nbsp; 另外一个取消任务的方法就是采用Future来管理任务,这是JDK5引入的，用于管理任务的生命周期，处理异常等。比如调用ExecutorService的sumit方法会返回一个Future来描述任务，而Future有一个cancel方法用于取消任务。<br />
&nbsp;&nbsp; 那么，如果任务调用了不可中断的阻塞方法，比如Socket的read、write方法，java.nio中的同步I/O，那么该怎么处理呢？简单地，关闭它们！参考下面的例子：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;net.rubyeye.concurrency.chapter7;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.IOException;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.InputStream;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.net.Socket;<br />
<br />
</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;展示对于不可中断阻塞的取消任务&nbsp;通过关闭socket引发异常来中断<br />
&nbsp;*&nbsp;<br />
&nbsp;*&nbsp;</span><span style="color: #808080;">@author</span><span style="color: #008000;">&nbsp;Admin<br />
&nbsp;*&nbsp;<br />
&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ReaderThread&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;Thread&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Socket&nbsp;socket;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;InputStream&nbsp;in;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ReaderThread(Socket&nbsp;socket)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.socket&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;socket;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.in&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;socket.getInputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;重写interrupt方法</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&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;interrupt()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(IOException&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">finally</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">.interrupt();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&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;run()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[]&nbsp;buf&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[</span><span style="color: #000000;">1024</span><span style="color: #000000;">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;count&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;in.read(buf);<br />
&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;">&nbsp;(count&nbsp;</span><span style="color: #000000;">&lt;</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;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
&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;">&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(count&nbsp;</span><span style="color: #000000;">&gt;</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;processBuff(buf,&nbsp;count);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(IOException&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;processBuff(</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[]&nbsp;buf,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;count);<br />
}<br />
</span></div>
&nbsp;&nbsp;&nbsp; Reader线程重写了<em>interrupt</em>方法，其中调用了socket的close方法用于中断read方法，最后，又调用了super.interrupt()，防止当调用可中断的阻塞方法时不能正常中断。<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/142344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-03 15:50 <a href="http://www.blogjava.net/killme2008/archive/2007/09/03/142344.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单的web server性能测试</title><link>http://www.blogjava.net/killme2008/archive/2007/08/29/141036.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 29 Aug 2007 10:10:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/08/29/141036.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/141036.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/08/29/141036.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/141036.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/141036.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 简单的web server性能测试，一般多线程方式与采用jdk5线程池的比较。&nbsp;&nbsp;<a href='http://www.blogjava.net/killme2008/archive/2007/08/29/141036.html'>阅读全文</a><img src ="http://www.blogjava.net/killme2008/aggbug/141036.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-08-29 18:10 <a href="http://www.blogjava.net/killme2008/archive/2007/08/29/141036.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java求字符串型逻辑表达式的bool值</title><link>http://www.blogjava.net/killme2008/archive/2007/08/06/134668.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 06 Aug 2007 04:37:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/08/06/134668.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/134668.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/08/06/134668.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/134668.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/134668.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; 这是最近在项目中的一个需求，已知a=3，求字符串"a&lt;=2"的值，也就是应该返回false。这个问题可大可小，就我们的应用场景也就是用来让用户自定义变量区间，比如类似下面这样的规则：a&lt;=2&nbsp;&nbsp;&nbsp; 返回积分系数1.02&lt;a&lt;=5&nbsp; 返回积分系数1.1a&gt;5&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;<a href='http://www.blogjava.net/killme2008/archive/2007/08/06/134668.html'>阅读全文</a><img src ="http://www.blogjava.net/killme2008/aggbug/134668.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-08-06 12:37 <a href="http://www.blogjava.net/killme2008/archive/2007/08/06/134668.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>portal学习（二）portlet开发之hello world</title><link>http://www.blogjava.net/killme2008/archive/2007/07/15/130428.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 15 Jul 2007 13:02:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/15/130428.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/130428.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/15/130428.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/130428.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/130428.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; portal开发的一个重要工作就是portlet的开发，网上一大堆hello world，都是最简单的，用PrintWriter输出字符串。今天介绍一下稍微复杂的，用户转到portlet的edit Model，该页面是有一个输入框和一个按钮，输入你的名字，然后提交，将转到此portlet的view Model并输出hello,your name。<br>&nbsp;&nbsp;&nbsp; portlet与servlet非常相似，因为portlet就是在servlet规范的基础上扩展的，并且portlet容器也是在servlet容器的基础上扩展，同serlvet一样，我们的HelloWorldPorlet需要强制继承自GenericPortlet类，GenericPortlet实现了Portlet接口,看看完整代码：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;net</span><span style="color: #000000;">.</span><span style="color: #000000;">rubyeye</span><span style="color: #000000;">.</span><span style="color: #000000;">portlets;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax</span><span style="color: #000000;">.</span><span style="color: #000000;">portlet</span><span style="color: #000000;">.</span><span style="color: #000000;">ActionResponse;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax</span><span style="color: #000000;">.</span><span style="color: #000000;">portlet</span><span style="color: #000000;">.</span><span style="color: #000000;">GenericPortlet;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax</span><span style="color: #000000;">.</span><span style="color: #000000;">portlet</span><span style="color: #000000;">.</span><span style="color: #000000;">PortletException;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax</span><span style="color: #000000;">.</span><span style="color: #000000;">portlet</span><span style="color: #000000;">.</span><span style="color: #000000;">PortletRequestDispatcher;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax</span><span style="color: #000000;">.</span><span style="color: #000000;">portlet</span><span style="color: #000000;">.</span><span style="color: #000000;">RenderRequest;<br></span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax</span><span style="color: #000000;">.</span><span style="color: #000000;">portlet</span><span style="color: #000000;">.</span><span style="color: #000000;">RenderResponse;<br><br>public&nbsp;class&nbsp;HelloWorldPortlet&nbsp;extends&nbsp;GenericPortlet&nbsp;{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@Override</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;void&nbsp;doEdit(RenderRequest&nbsp;req</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;RenderResponse&nbsp;res)<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;throws&nbsp;PortletException</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;IOException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res</span><span style="color: #000000;">.</span><span style="color: #000000;">setContentType(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">text/html</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">//</span><span style="color: #000000;">获取初始参数，在init</span><span style="color: #000000;">-</span><span style="color: #000000;">param中定义<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;jspName&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;getPortletConfig()</span><span style="color: #000000;">.</span><span style="color: #000000;">getInitParameter(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">edit-jsp</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PortletRequestDispatcher&nbsp;rd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;getPortletContext()</span><span style="color: #000000;">.</span><span style="color: #000000;">getRequestDispatcher(<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;&nbsp;&nbsp;&nbsp;&nbsp;jspName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rd</span><span style="color: #000000;">.</span><span style="color: #000000;">include(req</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;res);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@Override</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;void&nbsp;doView(RenderRequest&nbsp;req</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;RenderResponse&nbsp;res)<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;throws&nbsp;PortletException</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;IOException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res</span><span style="color: #000000;">.</span><span style="color: #000000;">setContentType(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">text/html</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">//</span><span style="color: #000000;">执行完processAction后设置了renderParamter，这里得到<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;msg&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;req</span><span style="color: #000000;">.</span><span style="color: #000000;">getParameter(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">msg</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">);<br>&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;PrintWriter&nbsp;out&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;res</span><span style="color: #000000;">.</span><span style="color: #000000;">getWriter();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">System</span><span style="color: #000000;">.</span><span style="color: #000000;">out</span><span style="color: #000000;">.</span><span style="color: #000000;">println(msg);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(msg&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;null)<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;out</span><span style="color: #000000;">.</span><span style="color: #0000ff;">write</span><span style="color: #000000;">(msg);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">//</span><span style="color: #000000;">默认输出是Hello&nbsp;World<br>&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;out</span><span style="color: #000000;">.</span><span style="color: #0000ff;">write</span><span style="color: #000000;">(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">Hello&nbsp;World!</span><span style="color: #000000; font-weight: bold;">View!"</span><span style="color: #000000;">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">//</span><span style="color: #000000;">actionURL调用的processAction<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@Override</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;processAction(ActionRequest&nbsp;req</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;ActionResponse&nbsp;res)<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;throws&nbsp;PortletException</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;IOException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">//</span><span style="color: #000000;">&nbsp;TODO&nbsp;Auto</span><span style="color: #000000;">-</span><span style="color: #000000;">generated&nbsp;method&nbsp;stub<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;req</span><span style="color: #000000;">.</span><span style="color: #000000;">getParameter(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">name</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">System</span><span style="color: #000000;">.</span><span style="color: #000000;">out</span><span style="color: #000000;">.</span><span style="color: #000000;">println(name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res</span><span style="color: #000000;">.</span><span style="color: #000000;">setRenderParameter(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">msg</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">hello,</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
&nbsp;&nbsp;&nbsp; 解释下代码,portlet默认有三种Model：view、edit和help，顾名思义分别对照浏览、编辑和帮助状态，其中只有view是必须的，当然还可以自定义model。在portlet就有相应的doXXX方法用于呈现相应的片段，portlet还有一个render(RenderRequest，RenderResponse),这个方法与doView等方法的关系类似serlvet中service与doGet、doHelp的关系，一般我们都不直接覆写render，而是实现具体的doXXX方法。回到这个例子,HelloWorldPortlet有两个Model：view和edit。<br>&nbsp;&nbsp;&nbsp; 在doView方法中很简单，首先需要设置ContentType，然后获取前面processAction设置的renderParamter，当然，一开始进入portlet是view，这个值根本没有，默认就用PrintWriter输出Hello World。<br>&nbsp;&nbsp;&nbsp; processAction用于处理ActionRequest的方法，和一般的servlet编程没有什么不同，请注意，processAction执行之后才是执行相应的render方法，并且与render<span style="font-weight: bold;">不共享</span>parameter，因此为了在doView中获得msg参数，我们需要通过ActionResponse的setRenderParameter来设定RenderRequest的Parameter。<br>&nbsp;&nbsp;&nbsp; doEdit方法就比较简单了，通过PortletConfig的getInitParameter(与ServletConfig一样了）获得属性edit-jsp的值——编辑页面的位置，然后将该页面include进portlet。<br>&nbsp;&nbsp;&nbsp; portlet需要一个配置文件来告诉portlets容器具体信息，这个文件同样放在WEB-INF目录下，并且名为portlet<span style="color: #000000;"></span><span style="color: #000000;"></span><span style="color: #000000;"></span><span style="color: #000000; font-weight: bold;"></span><span style="color: #000000; font-weight: bold;"></span><span style="color: #000000; font-weight: bold;"></span><span style="color: #000000;"></span><span style="color: #000000;"></span><span style="color: #000000; font-weight: bold;"></span><span style="color: #000000; font-weight: bold;"></span><span style="color: #000000; font-weight: bold;"></span><span style="color: #000000;"></span><span style="color: #000000;"></span><span style="color: #000000;"></span><span style="color: #000000;"></span><span style="color: #000000;"></span>.xml：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">&lt;?</span><span style="color: #ff00ff;">xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"</span><span style="color: #0000ff;">?&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">portlet-app&nbsp;</span><span style="color: #ff0000;">version</span><span style="color: #0000ff;">="1.0"</span><span style="color: #ff0000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xmlns</span><span style="color: #0000ff;">="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"</span><span style="color: #ff0000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xsi</span><span style="color: #0000ff;">="http://www.w3.org/2001/XMLSchema-instance"</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">portlet</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">portlet-name</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">HelloWorldPorlet_1</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">portlet-name</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">portlet-class</span><span style="color: #0000ff;">&gt;</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;net.rubyeye.porlets.HelloWorldPorlet<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">portlet-class</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">init-param</span><span style="color: #0000ff;">&gt;</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;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">name</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">edit-jsp</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">name</span><span style="color: #0000ff;">&gt;</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;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">value</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">/portlets/edit.jsp</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">value</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">init-param</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">supports</span><span style="color: #0000ff;">&gt;</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;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">mime-type</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">text/html</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">mime-type</span><span style="color: #0000ff;">&gt;</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;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">portlet-mode</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">view</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">portlet-mode</span><span style="color: #0000ff;">&gt;</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;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">portlet-mode</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">edit</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">portlet-mode</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">supports</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">portlet-info</span><span style="color: #0000ff;">&gt;</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;</span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">title</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;">HelloWorld</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">title</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">portlet-info</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">portlet</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">portlet-app</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br></span></div>
&nbsp; 信息非常清楚，就不多做解释了，edit-jsp的值是/portlets/edit.jsp，portlets容器就会去portlets目录下寻找edit.jsp。supports元素指定了portlet支持的Model以及Mime类型。更详细的配置请参考官方规范<br>&nbsp;&nbsp; 最后就是edit.jsp，需要用到portlets规范规定的标签，我们这里用到了actionURL，该标签用于form的action的生成，触发带有参数的request请求的processAction调用，当然还有一个renderURL，顾名思义仅是用于呈现，而非action的触发。请注意，form的method必须是post，因为portlets容器可能将一些状态信息写在url，使用post提交避免冲突。<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="background-color: #ffff00; color: #000000;">&lt;%</span><span style="background-color: #f5f5f5; color: #000000;">@taglib&nbsp;uri</span><span style="background-color: #f5f5f5; color: #000000;">=</span><span style="background-color: #f5f5f5; color: #000000;">"</span><span style="background-color: #f5f5f5; color: #000000;">http://java.sun.com/portlet</span><span style="background-color: #f5f5f5; color: #000000;">"</span><span style="background-color: #f5f5f5; color: #000000;">&nbsp;prefix</span><span style="background-color: #f5f5f5; color: #000000;">=</span><span style="background-color: #f5f5f5; color: #000000;">"</span><span style="background-color: #f5f5f5; color: #000000;">portlet</span><span style="background-color: #f5f5f5; color: #000000;">"</span><span style="background-color: #f5f5f5; color: #000000;">&nbsp;</span><span style="background-color: #ffff00; color: #000000;">%&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">portlet:defineObjects</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">div</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">form&nbsp;</span><span style="color: #ff0000;">method</span><span style="color: #0000ff;">="post"</span><span style="color: #ff0000;">&nbsp;action</span><span style="color: #0000ff;">="&lt;portlet:actionURL&nbsp;portletMode="</span><span style="color: #ff0000;">view"&nbsp;windowState</span><span style="color: #0000ff;">="normal"</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;">"&nbsp;&gt;<br>please&nbsp;input&nbsp;your&nbsp;name:<br></span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">input&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="text"</span><span style="color: #ff0000;">&nbsp;name</span><span style="color: #0000ff;">="name"</span><span style="color: #ff0000;">&nbsp;size</span><span style="color: #0000ff;">="10"</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">input&nbsp;</span><span style="color: #ff0000;">type</span><span style="color: #0000ff;">="submit"</span><span style="color: #ff0000;">&nbsp;value</span><span style="color: #0000ff;">="submit"</span><span style="color: #0000ff;">/&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">form</span><span style="color: #0000ff;">&gt;</span><span style="color: #000000;"><br></span></div>
<br>&nbsp; 在使用portlet规范规定的标签前，一定要先使用&lt;portlet:defineObjects/&gt;
标签，以便定义下列变量让jsp使用：<br>renderRequest<br>renderResponse<br>portletConfig<br><br>&nbsp;&nbsp;&nbsp; 我们通过actionURL标签产生指向本portlet的url，并且指定没有错误发生时这个portlet应该具有的Model是view，窗口大小为normal。最后部署并运行，因为不同的portal的部署方式和所需要的其他配置文件各不相同，这里就不详细介绍了。下面是在Bea Portal 10.0上的效果图：<br><br>1.一开始看到的是view Model，输出Hello World!View!:<br><img  src="http://www.blogjava.net/images/blogjava_net/killme2008/portlet-view.jpg" border="0"><br><br>2.点击左上角的edit链接进入edit model:<br><img  src="http://www.blogjava.net/images/blogjava_net/killme2008/portlet-edit.jpg" border="0"><br><br>3.输入dennis,提交，转到view model:<br><img  src="http://www.blogjava.net/images/blogjava_net/killme2008/portlet-action.jpg" border="0"><br><br><img src ="http://www.blogjava.net/killme2008/aggbug/130428.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-15 21:02 <a href="http://www.blogjava.net/killme2008/archive/2007/07/15/130428.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>portal学习（一）抄书</title><link>http://www.blogjava.net/killme2008/archive/2007/07/15/130423.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 15 Jul 2007 12:16:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/15/130423.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/130423.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/15/130423.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/130423.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/130423.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 这两天将网上下载的《JSR168 porlet标准手册汉化整理》和《Liferay Portal二次开发指南》认认真真地看了几遍，看了BEA站点上portal的getting start，写了hello world，算是正式开始学习portal了。感谢这么多人无私地分享知识。抄书。<br><br>第一节 Portal 规范<br>随着Portal 的兴起，越来越多的公司开始涉足Portal 产品开发，并组建各自的Portal 组<br>件和基于其的产品，比如IBM、BEA、MicroSoft、SAP、Apache 等。各个厂商的接口互不<br>兼容，给软件开发商以及开发人员带来诸多不便。<br>1.1.1 JSR168<br>为此，JCP 组织发布了JSR168(Java Specification Request)，Portlet Specification V1.0，<br>用来提供不同的Portal 和Portlet 之间的互通性。只要开发的Portlet 遵循JSR168，则就可以<br>在所有遵循JSR168 的Portal 上部署运行。<br>JSR168 中定义了Portal 的实现规范和接口，并对理想的Portlet 进行了详细的规划和描<br>述。<br>1.1.2 WSRP<br>WSRP 是OASIS Web Service for Remote Portlet 的缩写。WSRP 是Web Service 的一种新<br>的商业应用，一种新的标准，主要用来简化Portal 对于各种资源或者程序整合的复杂度，可<br>以避免编程带来的整合麻烦和问题。而且Portal 管理员可以从海量的WSRP 服务中选择需<br>要的功能用以整合到目前所用的Portal 中。它有三种角色：<br>①、生产者 􀃆 提供Portlet<br>②、消费者 􀃆 使用Portlet<br>③、终端用户 􀃆 最终用户<br>它的特点在于生产者将消费者所需要的信息通过WSRP 返回给消费者，这些信息是相对<br>标记片断，例如HTML、XHTML 等，可以直接嵌入用户的页面中，而不用像Web Service<br>一样开发用户端接口。<br>实现这个规范，Portal 可以跟各式各样的数据源打交道，彻底终结信息孤岛的窘境。
<br>第二节 什么是Portal<br>Portal 是基于Web 的，以&#8220;应用整合&#8221;和&#8220;消除信息孤岛&#8221;为最终目的，提供单点登<br>录、内容聚合、个性化门户定制等功能的综合信息系统。<br>完整的Portal 通常由Portal 服务器、Portlet 容器、Portlet 构成。<br>1.2.1 Portal 服务器<br>Portal 服务器是容纳Portlet 容器，支持Portlet 呈现的普通或者特殊Web 服务器。<br>Portal 服务器通常会提供个性化设置、单点登录、内容聚合、信息发布、权限管理等功能，<br>支持各种信息数据来源，并将这些数据信息放在网页中组合而成，提供个性化的内容定制，<br>不同权限的浏览者能够浏览不同的信息内容。通常，Portal 提供以下功能:<br>单点登录：Portal 通常采用ACL、SSL、LDAP 等业界标准的安全技术，提供对所有现有<br>应用系统的安全集成，只需在Portal 的唯一入口上登录一次，就可以访问所有应用系统和<br>数据。对于安全性要求较高的应用系统，如电子商务平台、交易系统等，通过扩展接口传递<br>用户身份信息，如数字证书信息、数字签名信息等，进行二次身份认证，保证单点登陆的安<br>全性。<br>权限控制:系统采用LDAP 对用户资源进行统一的管理，同时提供二次开发接口，可以<br>与其他应用系统的用户管理模块对接，并能随相关业务系统实时更新访问权限。通过完善的<br>授权机制及存取控制，用户访问权限控制到字段级别，确保用户只能访问具有权限的应用系<br>统及相关信息。<br>内容管理: 实现应用系统之间实时交换信息。采用多种缓存机制，保证内容交换的性能<br>和准确性。采用基于XML 的Rich Site Summary (RSS)标准，迅速在各应用系统之间传播最<br>新变化。<br>信息发布: 实现信息门户内容的动态维护。动态网站系统可与OA 协同办公系统、知识<br>管理系统等集成，网站信息须经OA 系统的审批流程流转通过后或知识管理平台设置具有外<br>部共享权限后才可正式发布，真正实现内外信息发布的同步。<br>文件管理: 系统实现无缝集成多种数据源，包括：数据库、文档（Office 文档、PDF、<br>AutoCAD、甚至ZIP 文档）、Web 网页、FTP 站点等，并对数据按业务要求和职务特点加以分<br>析整理，通过统一Web 界面主动推送(Push)至用户的门户桌面，帮助用户做出及时、正确的<br>决策。<br>1.2.2 Portlet 容器<br>Portlet 容器提供Portlet 执行的环境，包含很多Portlet 并管理它们的生命周期，保<br>存Portlet 的定制信息。<br>一个Portal 容器接收到来自Portal 的请求后，接着将这个请求传递给存在Portal 容<br>器的Portlet 执行。Portlet 容器没有义务去组合Portlet 产生的信息內容，这个工作必<br>须由Portal 来处理。Portal 和 Portal 容器可以放在一起视为同一个系统的组件，或者分<br>开成为两个独立的组件。<br>Portlet 容器是普通Web Servlet 容器的扩展，所以一个Portlet 容器可以构建于一个<br>已经存在的Servlet 容器或者可能实现全部Web Servlet 容器的全部功能。无论Portlet<br>容器怎么实现，它的运行环境总是假定它支持Servlet2.3 规范。
<br><br>通常，Portlet 容器扩展自普通的Servlet 容器。<br>第三节 什么是Portlet<br>Portlet 是Portal 中最重要的组件，负责在Portal 中呈现信息内容，有相应的生命周<br>期。通过自定义Portlet，用户很容易定义个性化的Portal 页面。Portlet 由Portlet 容器<br>负责管理、处理请求并返回动态页面，可以作为Portal 的可即插即用的界面组件。<br>1.3.1 Portlet<br>一个Portlet是以Java技术为技术的Web组件，由Portlet容器所管理，专门处理客户的<br>信息请求以及产生各种动态的信息内容。Portlet 为可插式的客户界面组件，提供呈现层成<br>为一个信息系统。<br>这些由Portlet产生的内容也被称为片段，而片段是具有一些规则的标记( HTML、XHTML、<br>WML )，而且可以和其他的片段组合而成一个复杂的文件。一个或多个 Portlet 的内容聚合<br>而成为一个 Portal 网页。而 Portlet 的生命周期是被 Portlet 容器所管理控制的。<br>客户端和Portlet的互动是由Portal通过典型的请求/响应方式实现，正常来说，客户会<br>和Portlet所产生的内容互动，举例来说，根据下一步的连接或者是确认送出的表单，结果<br>Portal将会接收到Portlet的动作，将这个处理状况转向到目标Portlet。这些Portlet 内容<br>的产生可能会因为不同的使用者而有不同的变化，完全是根据客户对于这个Portlet的设置。<br>1.3.2 Portlet 与Servlet 的关系<br>Portlet 被定义成为一个新的组件，具有新的明确的界面与行为。为了尽可能与现有的<br>Servlet 结合达到重复使用的目的，Portlet 的规范利用了 Servlet 的规范，许多观念都<br>很相似的，结合 Portlet、Servlet 及 Jsp 在同一个网站系统中，我们称为Portlet 应用 。<br>在同一个 Portlet 应用 中，他们将分享同一个类加载器(ClassLoader)，上下文(Context)<br>及 Session。<br>①、Portlet 和 Servlet 的相似之处<br>@ Portlet 也是 Java 技术的 web 组件<br>@ Portlet 也是有特定的 container 在管理<br>@ Portlet 可以动态产生各种内容<br>@ Portlet 的生命周期由 container 所管理<br>@ Portlet 和客户端的互动是通过 request/response 的机制<br>②、Portlet 和 Servlet 也有一些不同<br>8<br>@ Portlet 只产生 markup 信息片段，不是完整的网页文件。而 Portal 会将所有的<br>Portlet markup 信息片段放到一个完整的 Portal 网页。<br>@ Portlet 不会和 URL 有直接的关系<br>@ 客户端必须通过 portal 系统才能和 Portlet 互动<br>@ Portlet 有一些定义好的 request 处理，action request 以及 render request。<br>@ Portlet 默认定义 Portlet modes 及窗口状态可以指出在网页中该 Portlet 的哪个功<br>能正在执行及现在的 状态。<br>@ Portlet 可以在同一个 portal 网页之中存在多个。
<br>③、Portlet 有一些附加的功能是 Servlet 所没有的<br>@ Portlet 能够存取及储存永久配置文件及定制资料。<br>@ Portlet 可以存取使用者数据<br>@ Portlet 具有 URL 的重写功能在文件中去动态建立连结，允许 portal server 不用去<br>知道如何在网页的片 段之中建立连结及动作。<br>@ Portlet 可以储存临时性的数据在 Portlet session 之中，拥有两个不同的范围 ：<br>application-wide scope 及 Portlet private scope 。<br>④、Portlet 不具有一些功能， 但是 Servlet 却有提供<br>@ Servlet 具有设置输出的文字编码( character set encoding)方式<br>@ Servlet 可以设置 HTTP 输出的 header<br>@ Servlet 才能够接收客户对于 portal 发出的 URL 请求<br>1.3.3 Portlet 的生命周期<br>一个Portlet有着良好的生命周期管理，定义了怎样装载，实例化和初始化，怎样响应来<br>自客户端的请求及怎样送出服务。这个Portlet生命周期由Portlet接口的init，processAction，<br>render和destroy方法来表达。<br>载入和实例化:Portlet 容器负责载入和实例化Portlet。当Portlet 容器运行Portlet 应用或<br>者延迟到Portlet 需要服务使用者的请求时，Portlet 就会被载入并实例化。载入Portlet 类后，<br>Portlet 类随即被实例化。<br>初始化:Portlet 类实例化后，Portlet 容器还需要初始化Portlet。以调用Portlet 去响应客<br>户端的请求。Portlet 容器呼叫Portlet 接口中的init 方法初始化Portlet。扩展自PortletConfig<br>的类可以取出定义在部署描述文件中的初始化参数，以及Resource Bundle。<br>初始化异常:在 Portlet 初始化期间，Portlet 可能会丟出 UnavailableException 或<br>PortletException 异常。此时，Portlet 容器不能把 Portlet 置入已启动的服务，并且 Portlet<br>容器必需释放这个 Portlet。 destory 方法不能被呼叫，因为初始化被认为执行失败。发生 失<br>败后，Portlet 容器会尝试着重新实例化及初始化 Portlet。这个异常处理的规则是：由一个<br>UnavailableException 指定一个不能执行的最小时间，当此异常发生时，Portlet 容器必需等<br>到指定时间过去后才产生并且初始化一个新的 Portlet。<br>在初始化过程中所丟出的 Runtime Exception 异常，被当作 PortletException 来处理。
<br><br><img src ="http://www.blogjava.net/killme2008/aggbug/130423.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-15 20:16 <a href="http://www.blogjava.net/killme2008/archive/2007/07/15/130423.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何设置一个基本的OpenLDAP Server(转载）</title><link>http://www.blogjava.net/killme2008/archive/2007/07/14/130281.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 14 Jul 2007 08:08:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/14/130281.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/130281.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/14/130281.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/130281.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/130281.html</trackback:ping><description><![CDATA[<p>如何设置一个基本的OpenLDAP Server <br>本文出自:http://www.linuxforum.net 作者:吴阿亭 Jephe wu (2001-09-04 15:00:01) </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一. 目的&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本文旨在介绍如何安装OpenLDAP并且设置一个公司内部的集中化的邮件地址薄服务器供客 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 户端查询。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基本上，OpenLDAPg还应用在其它许多方面，象集中化的用户帐号验证服务器,但邮件地址 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 薄查询是最常用的。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 二. 安装&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从<a href="http://www.openldap.org/">www.openldap.org</a>下载最新的openldap软件包，按照编译和安装的步骤，依次运行： </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #tar cvfz openldap-stable-20010524.tgz&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #cd openldap-2.0.11&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #./configure&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #make depend&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #make&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #make test&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #make install&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我的操作环境是redhat 6.1，如果没有遇到任何错误，最后默认安装LDAP后台程序slapd <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 到目录/usr/local/libexec;配置文件在目录/usr/local/etc/openldap/ 并且放各种 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OpenLDAP工具 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ldapadd,ldapdelete,ldapmodify,ldapmodrdn,ldappasswd,ldapsearch 在目录 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /usr/local/bin,运行时数据库在/usr/local/var/openldap-ldbm 。&nbsp; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 三. 设置&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1) 更改配置文件/usr/local/etc/openldap/slapd.conf&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在include /usr/local/etc/openldap/schema/core.schema这行后面加上下面的行， <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 包括所有的方案。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/corba.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/cosine.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/inetorgperson.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/java.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/krb5-kdc.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/misc.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/nadf.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/nis.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/openldap.schema&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2) 在文件slapd.conf的"ldbm database definitions"部分更改相应的 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; suffix,rootdn行如下&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; database ldbm&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; suffix "o=yourdomain,c=us"&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rootdn "cn=root,o=yourdomain,c=us"&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rootpw secret&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; directory /usr/local/var/openldap-ldbm&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有各种格式你可以用，这里我用的是o=yourdomain,c=us 说明你的公司域名和所在的国 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 家或地区&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rootdn的格式安装后默认为cn=Manager,这里改为root完全是自己的喜好,这样符合 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Unix/Linux中root具有最高权限的传统。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3) 现在可以启动slapd了，运行/usr/local/libexec/slapd 。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以考虑把/usr/local/bin and /usr/local/libexec加到搜索路径中，即加到 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /etc/profile&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 中的PATH行:&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PATH="$PATH:/usr/X11R6/bin:/usr/local/bin:/usr/local/libexec"&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样下次登录后只需键入 slapd 。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4) 测试ldap server是否正常工作。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行下面的命令检查是否有相应的输出。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ldapsearch -x -b 'o=yourdomain,c=us' '(objectclass=*)'&nbsp; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5) 编辑.ldif文本文件，用ldapadd添加记录进入LDAP数据库。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文件内容如下：&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dn: o=yourdomain,c=us&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectclass: dcobject&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectclass: organization&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o: yourdomain&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dc: yourdomain&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dn: cn=Jephe Wu,o=yourdomain,c=us&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectclass: inetorgperson&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cn: Jephe Wu&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sn: Wu&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mail: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#106;&#101;&#112;&#104;&#101;&#95;&#119;&#117;&#64;&#121;&#111;&#117;&#114;&#100;&#111;&#109;&#97;&#105;&#110;&#46;&#99;&#111;&#109;">jephe_wu@yourdomain.com</a>&nbsp; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......more users......&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 依次类推，添加每个人的记录进入该文件中，注意对象类型 inetorgperson 至少必须要 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有cn和sn&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,这里我们用cn,sn,mail三项定义,这对我们的邮件地址薄功能来说已经足够。你还可以 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 定义象&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mobile, homephone,pager......等等。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然后用下面的命令添加上面的.ldif文件进入LDAP数据库&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ldapadd -x -D "cn=root,o=yourdomain,c=us" -w secret -f <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "yourldiffilename"&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注：上面的文件的第一部分"dn: o=yourdomain,c=us"是必须的，否则不能添加数据。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用你的公司的域名替换上面的"yourdomain"。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6) 设置Outlook Express, 允许用LDAP服务器查询邮件地址。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "工具/帐号/添加--目录服务"，填入你的服务器的IP地址或者主机全称域名，在下一个屏 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 幕中选yes以允许用目录服务来查询地址，最后在"目录服务"栏中选中刚才设置的项目击 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;属性/高级",在"搜索库"中填入&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "o=yourdomain,c=us" 。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Netscape请根据上面的信息设置相应的选项。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 四. 常见使用问题&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1) 能启动slapd 没有问题，但不能添加数据库，运行ldapadd添加时出错 "ldap_bind: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cannot contact LDAP Server" 。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 答: 最可能的原因是在/etc/hosts中没有127.0.0.1 localhost项目。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2) 注意查询顺序: 如果在Outlook Express的地址薄中有内容，则检查地址时地址薄优 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先，如果在本地地址薄中找不到相应记录，然后再查询LDAP服务器。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3) 用下面的命令确信客户端与LDAP服务器有通讯,在服务器运行下面的命令，然后在OE中 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 测试检查地址，你将会得到查询LDAP数据库的连接过程的输出。&nbsp; </p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # tcpdump port 389&nbsp;
<br><img src ="http://www.blogjava.net/killme2008/aggbug/130281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-14 16:08 <a href="http://www.blogjava.net/killme2008/archive/2007/07/14/130281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>