﻿<?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-技术源于思维，思维远比技术重要</title><link>http://www.blogjava.net/standlww/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 12 Apr 2026 06:02:43 GMT</lastBuildDate><pubDate>Sun, 12 Apr 2026 06:02:43 GMT</pubDate><ttl>60</ttl><item><title>关于Opener，parent，top，self等窗体属性的研究</title><link>http://www.blogjava.net/standlww/archive/2009/04/28/267807.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Mon, 27 Apr 2009 16:01:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2009/04/28/267807.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/267807.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2009/04/28/267807.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/267807.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/267807.html</trackback:ping><description><![CDATA[<p>1.Opener：获取创建本窗口的窗口的引用，不在本窗口的对象层次体系中</p>
<p>只能在用window.open打开的页面中窗口中可以访问到opener属性，而对于用showModalDialog和showModalessDialog弹出的窗口则不能访问到，其opener属性引用为空。</p>
<p>2.parent，top：获取的是对本窗口中对象层次元素的引用，对于用iframe或者frame的较有实际意义<br />
对于用window.open和showModalDialog以及showModalessDialog打开的窗口而言，返回的是本窗口对象层次的元素引用，对于这种情况，parent，top，self三者的引用相同，都是当前的窗体自身，但对于窗体中的frame和iframe加载的页面元素来说，返回的则不相同。parent 返回的时包含该iframe的页面窗口引用，top则返回最上层的窗口引用，self当然返回的仍然是自身的引用。<br />
&nbsp;<br />
3.self，window都是获取当前页面窗口自身对象的引用<br />
每个页面自身代码中访问页面自身窗体可以采用self和window来访问到。<br />
&nbsp;<br />
4.利用window参数传递和dialogArguments来获取弹出窗口的窗口引用<br />
为了能够在用showModalDialog和showModalessDialog弹出窗口中引用到弹出窗口的引用，我们可以在showModalDialog和showModalessDialog的第二个参数传入window，然后再弹出的页面中用dialogArguments来获取刚才传入的window，即弹出窗口的窗口的引用。<br />
</p>
 <img src ="http://www.blogjava.net/standlww/aggbug/267807.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2009-04-28 00:01 <a href="http://www.blogjava.net/standlww/archive/2009/04/28/267807.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我对wait()的一点理解</title><link>http://www.blogjava.net/standlww/archive/2008/10/20/235539.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Mon, 20 Oct 2008 13:20:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2008/10/20/235539.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/235539.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2008/10/20/235539.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/235539.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/235539.html</trackback:ping><description><![CDATA[<p>wait()与sleep()的区别相信很多人都懂了，在这里我就不说了。<br />
&nbsp; </p>
<p><span>wait()，<span style="background-color: yellow">对此对象调用wait方法导致本线程放弃对象锁</span></span><span>，进入等待此对象的等待锁定池，只有针对此对象发出</span>notify<span>方法（或</span>notifyAll<span>）后本线程才进入对象锁定池准备获得对象锁进入运行状态。</span></p>
<p><br />
public class ThreadTest {</p>
<p>&nbsp;<br />
&nbsp;static int i=0;<br />
&nbsp;<br />
&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;new ThreadTest().setInt(5);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;System.out.println(i);</p>
<p>&nbsp;}<br />
&nbsp;<br />
&nbsp;public&nbsp; void setInt(int i){<br />
&nbsp;&nbsp;this.i=i;<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;this.wait();<br />
&nbsp;&nbsp;} catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;}</p>
<p>}<br />
</p>
<p dir="ltr"><br />
因此在对上述概念较充分理解后，你就会明白以上这个程序错在哪里？<br />
<br />
在eclipse编写和编译并没有错，但当运行后eclipse提示：IllegalMonitorStateException: current thread not owner<br />
<br />
Exception in thread "main" java.lang.IllegalMonitorStateException: current thread not owner<br />
&nbsp;at java.lang.Object.wait(Native Method)<br />
&nbsp;at java.lang.Object.wait(Unknown Source)<br />
&nbsp;at standlww.project.ThreadTest.setInt(ThreadTest.java:21)<br />
&nbsp;at standlww.project.ThreadTest.main(ThreadTest.java:12)Exception in thread "main" java.lang.IllegalMonitorStateException: current thread not owner<br />
&nbsp;at java.lang.Object.wait(Native Method)<br />
&nbsp;at java.lang.Object.wait(Unknown Source)<br />
&nbsp;at standlww.project.ThreadTest.setInt(ThreadTest.java:21)<br />
&nbsp;at standlww.project.ThreadTest.main(ThreadTest.java:12)<br />
<br />
原因在于<span style="background-color: yellow">对此对象调用wait方法导致本线程放弃对象锁</span><span style="background-color: yellow">对此对象调用wait方法导致本线程放弃对象锁<span style="background-color: #ffffff">，而&nbsp;public&nbsp; void setInt(int i)方法没有加锁，是个不需要加锁就能运行得方法。<br />
</span></span><br />
</p>
<img src ="http://www.blogjava.net/standlww/aggbug/235539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2008-10-20 21:20 <a href="http://www.blogjava.net/standlww/archive/2008/10/20/235539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于生产者与消费者之间的问题</title><link>http://www.blogjava.net/standlww/archive/2008/10/20/235534.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Mon, 20 Oct 2008 12:55:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2008/10/20/235534.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/235534.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2008/10/20/235534.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/235534.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/235534.html</trackback:ping><description><![CDATA[关于生产者与消费者之间的问题，其实在你准确理解了线程的概念和方法的用法后，就很容易理解了。<br />
<br />
以下是偶写的一个关于生产者与消费者的程序，看看对你理解有没有帮助。<br />
<br />
<p>//生产者<br />
&nbsp;class Producer implements Runnable{<br />
&nbsp;private WOWOTou wwt=null;<br />
&nbsp;private Basket bs=null;<br />
&nbsp;private static int id=1;<br />
&nbsp;private static boolean state=true;<br />
&nbsp;<br />
&nbsp;Producer(Basket bs){<br />
&nbsp;&nbsp;this.bs=bs;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public&nbsp; WOWOTou produce(){<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;Thread.sleep( (long) (Math.random()*8000));<br />
&nbsp;&nbsp;} catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;wwt=new WOWOTou(id);<br />
<br />
&nbsp; //输出调试语句<br />
&nbsp;&nbsp;System.out.println();<br />
&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()+"生产了id为"+id+"的包子");&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;id++;<br />
&nbsp;&nbsp;return wwt;<br />
&nbsp;}</p>
<p>&nbsp;public void push(){<br />
&nbsp;&nbsp;bs.push(wwt);<br />
&nbsp;&nbsp;wwt=null;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void run() {<br />
&nbsp;<br />
&nbsp;&nbsp;while(state){<br />
&nbsp;&nbsp;&nbsp;synchronized(this){<br />
&nbsp;&nbsp;&nbsp;&nbsp;produce();<br />
&nbsp;&nbsp;&nbsp;&nbsp;push();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp; <br />
&nbsp;}<br />
&nbsp;<br />
}</p>
<p><br />
<br />
<br />
//消费者<br />
class Custmer implements Runnable{<br />
&nbsp;<br />
&nbsp;private Basket bs=null;<br />
&nbsp;private WOWOTou wwt=null;<br />
&nbsp;private static boolean state=true;<br />
&nbsp;<br />
&nbsp;public Custmer(Basket bs) {<br />
&nbsp;&nbsp;this.bs = bs;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;public&nbsp; void cousme(){<br />
&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;&nbsp;Thread.sleep((long) (Math.random()*8000));<br />
&nbsp;&nbsp;}catch(InterruptedException e){<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;//&nbsp;输出调试语句<br />
&nbsp;&nbsp;System.out.println();<br />
&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()+"消费id为"+wwt.getWOWOTouID()+"的包子");&nbsp;&nbsp;<br />
<br />
&nbsp;&nbsp;wwt=null;<br />
&nbsp;&nbsp;<br />
&nbsp;}</p>
<p>&nbsp;public void pop(){<br />
&nbsp;&nbsp;wwt=bs.pop();<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void run() {<br />
&nbsp;&nbsp;while(state){<br />
&nbsp;&nbsp;&nbsp;synchronized(this){<br />
&nbsp;&nbsp;&nbsp;&nbsp;pop();<br />
&nbsp;&nbsp;&nbsp;&nbsp;cousme();<br />
&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;}</p>
<p><br />
}</p>
<p>&nbsp;<br />
</p>
<p><br />
//装WOWOTou的Basket<br />
class Basket{<br />
&nbsp;<br />
&nbsp;private int index=0;<br />
&nbsp;private&nbsp; final static int max=5;<br />
&nbsp;private WOWOTou wwt=null;<br />
&nbsp;private WOWOTou[] wwtbs=new WOWOTou[5];<br />
&nbsp;private Producer p=null;<br />
&nbsp;private static Basket bs=null;<br />
&nbsp;<br />
&nbsp;private Basket(){}<br />
&nbsp;<br />
&nbsp;public synchronized static Basket getBasket(){<br />
&nbsp;&nbsp;if(bs==null)<br />
&nbsp;&nbsp;&nbsp;bs=new Basket();<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;return bs;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;public synchronized void&nbsp; push(WOWOTou wwt){<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;while(index==max){<br />
&nbsp;&nbsp;&nbsp;System.out.println("包子满了，赶紧吃包子");<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.wait();<br />
&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;this.notify();<br />
<br />
&nbsp;//输出调试语句<br />
&nbsp;&nbsp;&nbsp;System.out.println();<br />
&nbsp;&nbsp;&nbsp;System.out.println("这是"+Thread.currentThread().getName()+"生产的id为"+wwt.getWOWOTouID()+"的包子");<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;wwtbs[index++]=wwt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public synchronized WOWOTou pop(){<br />
&nbsp;&nbsp;while(index==0){<br />
&nbsp;&nbsp;&nbsp;System.out.println();<br />
&nbsp;&nbsp;&nbsp;System.out.println("没包子了，赶紧生产包子");<br />
&nbsp;&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.wait();<br />
&nbsp;&nbsp;&nbsp;}catch(InterruptedException e){<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;this.notify();<br />
&nbsp;&nbsp;&nbsp;if(index&gt;0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;index--;<br />
<br />
&nbsp; //输出调试语句<br />
&nbsp;&nbsp; System.out.println();<br />
&nbsp;&nbsp; System.out.println(Thread.currentThread().getName()+"拿到id为"+wwtbs[index].getWOWOTouID()+"的包子");&nbsp;<br />
<br />
&nbsp;&nbsp;return wwtbs[index];<br />
&nbsp;}<br />
}</p>
<p>&nbsp;</p>
<p><br />
class WOWOTou{<br />
&nbsp;<br />
&nbsp;private int id=0;<br />
&nbsp;<br />
&nbsp;WOWOTou(int id){<br />
&nbsp;&nbsp;this.id=id;<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public int getWOWOTouID(){<br />
&nbsp;&nbsp;return id;<br />
&nbsp;}<br />
}</p>
<br />
<br />
当你明白线程后，就应该考虑多线程和线程的性能问题，尽量减小锁的粒度，但要注意死锁问题。 
<img src ="http://www.blogjava.net/standlww/aggbug/235534.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2008-10-20 20:55 <a href="http://www.blogjava.net/standlww/archive/2008/10/20/235534.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java JDK1.5 线程池的使用</title><link>http://www.blogjava.net/standlww/archive/2008/10/19/235301.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Sun, 19 Oct 2008 06:49:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2008/10/19/235301.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/235301.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2008/10/19/235301.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/235301.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/235301.html</trackback:ping><description><![CDATA[&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;&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; Java JDK1.5 线程池使用<br />
<br />
<br />
<p class="sysBr500 text" align="left">一、简介<br />
线程池类为 java.util.concurrent.ThreadPoolExecutor，常用构造方法为：<br />
<br />
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,<br />
long keepAliveTime, TimeUnit unit,<br />
BlockingQueue&lt;Runnable&gt; workQueue,<br />
RejectedExecutionHandler handler)</p>
<p class="sysBr500 text" align="left">corePoolSize： 线程池维护线程的最少数量<br />
maximumPoolSize：线程池维护线程的最大数量<br />
keepAliveTime： 线程池维护线程所允许的空闲时间<br />
unit： 线程池维护线程所允许的空闲时间的单位<br />
workQueue： 线程池所使用的缓冲队列<br />
handler： 线程池对拒绝任务的处理策略<br />
<br />
一个任务通过 execute(Runnable)方法被添加到线程池，任务就是一个 Runnable类型的对象，任务的执行方法就是 Runnable类型对象的run()方法。<br />
<br />
当一个任务通过execute(Runnable)方法欲添加到线程池时：<br />
<br />
如果此时线程池中的数量小于corePoolSize，即使线程池中的线程都处于空闲状态，也要创建新的线程来处理被添加的任务。</p>
<p class="sysBr500 text" align="left">如果此时线程池中的数量等于 corePoolSize，但是缓冲队列 workQueue未满，那么任务被放入缓冲队列。</p>
<p class="sysBr500 text" align="left">如果此时线程池中的数量大于corePoolSize，缓冲队列workQueue满，并且线程池中的数量小于maximumPoolSize，建新的线程来处理被添加的任务。</p>
<p class="sysBr500 text" align="left">如果此时线程池中的数量大于corePoolSize，缓冲队列workQueue满，并且线程池中的数量等于maximumPoolSize，那么通过 handler所指定的策略来处理此任务。<br />
<br />
也就是：处理任务的优先级为：<br />
核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize，如果三者都满了，使用handler处理被拒绝的任务。<br />
<br />
当线程池中的线程数量大于 corePoolSize时，如果某线程空闲时间超过keepAliveTime，线程将被终止。这样，线程池可以动态的调整池中的线程数。<br />
<br />
unit可选的参数为java.util.concurrent.TimeUnit中的几个静态属性：<br />
NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。<br />
<br />
workQueue我常用的是：java.util.concurrent.ArrayBlockingQueue<br />
<br />
handler有四个选择：<br />
ThreadPoolExecutor.AbortPolicy()<br />
抛出java.util.concurrent.RejectedExecutionException异常<br />
ThreadPoolExecutor.CallerRunsPolicy()<br />
重试添加当前的任务，他会自动重复调用execute()方法<br />
ThreadPoolExecutor.DiscardOldestPolicy()<br />
抛弃旧的任务<br />
ThreadPoolExecutor.DiscardPolicy()<br />
抛弃当前的任务</p>
<br />
<br />
<br />
二、一般用法举例<br />
//------------------------------------------------------------<br />
//TestThreadPool.java<br />
//package cn.simplelife.exercise;
<p class="sysBr500 text" align="left">import java.io.Serializable;<br />
import java.util.concurrent.ArrayBlockingQueue;<br />
import java.util.concurrent.ThreadPoolExecutor;<br />
import java.util.concurrent.TimeUnit;</p>
<p class="sysBr500 text" align="left">public class TestThreadPool {</p>
<p class="sysBr500 text" align="left">private static int produceTaskSleepTime = 2;<br />
private static int consumeTaskSleepTime = 2000;<br />
private static int produceTaskMaxNumber = 10;<br />
<br />
public static void main(String[] args) {</p>
<p class="sysBr500 text" align="left">//构造一个线程池<br />
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3,<br />
TimeUnit.SECONDS, new ArrayBlockingQueue&lt;Runnable&gt;(3),<br />
new ThreadPoolExecutor.DiscardOldestPolicy());</p>
<p class="sysBr500 text" align="left">for(int i=1;i&lt;=produceTaskMaxNumber;i++){<br />
try {<br />
//产生一个任务，并将其加入到线程池<br />
String task = "task@ " + i;<br />
System.out.println("put " + task);<br />
threadPool.execute(new ThreadPoolTask(task));<br />
<br />
//便于观察，等待一段时间<br />
Thread.sleep(produceTaskSleepTime);<br />
} catch (Exception e) {<br />
e.printStackTrace();<br />
}<br />
}<br />
}</p>
<p class="sysBr500 text" align="left">/**<br />
* 线程池执行的任务<br />
* @author hdpan<br />
*/<br />
public static class ThreadPoolTask implements Runnable,Serializable{<br />
private static final long serialVersionUID = 0;<br />
//保存任务所需要的数据<br />
private Object threadPoolTaskData;<br />
<br />
ThreadPoolTask(Object tasks){<br />
this.threadPoolTaskData = tasks;<br />
}<br />
public void run(){<br />
//处理一个任务，这里的处理方式太简单了，仅仅是一个打印语句<br />
System.out.println("start .."+threadPoolTaskData);<br />
try {<br />
////便于观察，等待一段时间<br />
Thread.sleep(consumeTaskSleepTime);<br />
} catch (Exception e) {<br />
e.printStackTrace();<br />
}<br />
threadPoolTaskData = null;<br />
}<br />
public Object getTask(){<br />
return this.threadPoolTaskData;<br />
}<br />
}<br />
}<br />
//------------------------------------------------------------<br />
说明：<br />
1、在这段程序中，一个任务就是一个Runnable类型的对象，也就是一个ThreadPoolTask类型的对象。</p>
<p class="sysBr500 text" align="left">2、一般来说任务除了处理方式外，还需要处理的数据，处理的数据通过构造方法传给任务。</p>
<p class="sysBr500 text" align="left">3、在这段程序中，main()方法相当于一个残忍的领导，他派发出许多任务，丢给一个叫 threadPool的任劳任怨的小组来做。</p>
<p class="sysBr500 text" align="left">这个小组里面队员至少有两个，如果他们两个忙不过来，任务就被放到任务列表里面。</p>
<p class="sysBr500 text" align="left">如果积压的任务过多，多到任务列表都装不下(超过3个)的时候，就雇佣新的队员来帮忙。但是基于成本的考虑，不能雇佣太多的队员，至多只能雇佣 4个。</p>
<p class="sysBr500 text" align="left">如果四个队员都在忙时，再有新的任务，这个小组就处理不了了，任务就会被通过一种策略来处理，我们的处理方式是不停的派发，直到接受这个任务为止(更残忍！呵呵)。</p>
<p class="sysBr500 text" align="left">因为队员工作是需要成本的，如果工作很闲，闲到 3SECONDS都没有新的任务了，那么有的队员就会被解雇了，但是，为了小组的正常运转，即使工作再闲，小组的队员也不能少于两个。</p>
<p class="sysBr500 text" align="left">4、通过调整 produceTaskSleepTime和 consumeTaskSleepTime的大小来实现对派发任务和处理任务的速度的控制，改变这两个值就可以观察不同速率下程序的工作情况。</p>
<p class="sysBr500 text" align="left">5、通过调整4中所指的数据，再加上调整任务丢弃策略，换上其他三种策略，就可以看出不同策略下的不同处理方式。</p>
<p class="sysBr500 text" align="left">6、对于其他的使用方法，参看jdk的帮助，很容易理解和使用。</p>
<br />
转自：http://hi.baidu.com/gladfeel/blog/item/b52338731dd6c3198701b0b3.html
<img src ="http://www.blogjava.net/standlww/aggbug/235301.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2008-10-19 14:49 <a href="http://www.blogjava.net/standlww/archive/2008/10/19/235301.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>全面解决五大数据库死锁的问题</title><link>http://www.blogjava.net/standlww/archive/2008/10/18/235157.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Sat, 18 Oct 2008 05:05:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2008/10/18/235157.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/235157.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2008/10/18/235157.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/235157.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/235157.html</trackback:ping><description><![CDATA[http://tech.ccidnet.com/zt/sisuo/
<img src ="http://www.blogjava.net/standlww/aggbug/235157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2008-10-18 13:05 <a href="http://www.blogjava.net/standlww/archive/2008/10/18/235157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 线程池的原理与实现</title><link>http://www.blogjava.net/standlww/archive/2008/10/17/235100.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Fri, 17 Oct 2008 15:20:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2008/10/17/235100.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/235100.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2008/10/17/235100.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/235100.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/235100.html</trackback:ping><description><![CDATA[最近在学习线程池、内存控制等关于提高程序运行性能方面的编程技术，在网上看到有一哥们写得不错，故和大家一起分享。<br />
<br />
[分享]Java 线程池的原理与实现<br />
<br />
<br />
这几天主要是狂看源程序，在弥补了一些以前知识空白的同时，也学会了不少新的知识（比如 NIO），或者称为新技术吧。<br />
线程池就是其中之一，一提到线程，我们会想到以前《操作系统》的生产者与消费者，信号量，同步控制等等。<br />
一提到池，我们会想到数据库连接池，但是线程池又如何呢？<br />
<br />
<br />
<strong>建议</strong>：在阅读本文前，先理一理同步的知识，特别是syncronized同步关键字的用法。<br />
关于我对同步的认识，要缘于大三年的一本书，书名好像是 Java 实战，这本书写得实在太妙了，真正的从理论到实践，从截图分析到.class字节码分析。哇，我想市场上很难买到这么精致的书了。作为一个Java爱好者，我觉得绝对值得一读。<br />
我对此书印象最深之一的就是：equal()方法，由浅入深，经典！<br />
还有就是同步了，其中提到了我的几个编程误区，以前如何使用同步提高性能等等，通过学习，使我对同步的认识进一步加深。<br />
<br />
<br />
<font size="3"><strong>简单介绍</strong></font><br />
<br />
&nbsp;&nbsp;&nbsp; 创建线程有两种方式：继承Thread或实现Runnable。Thread实现了Runnable接口，提供了一个空的run()方法，所以不论是继承Thread还是实现Runnable，都要有自己的run()方法。<br />
&nbsp;&nbsp;&nbsp; 一个线程创建后就存在，调用start()方法就开始运行（执行run()方法），调用wait进入等待或调用sleep进入休眠期，顺利运行完毕或休眠被中断或运行过程中出现异常而退出。<br />
<br />
<strong>wait和sleep比较：</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep方法有：sleep(long millis)，sleep(long millis, long nanos)，调用sleep方法后，当前线程进入休眠期，暂停执行，但该线程继续拥有监视资源的所有权。到达休眠时间后线程将继续执行，直到完成。若在休眠期另一线程中断该线程，则该线程退出。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait方法有：wait()，wait(long timeout)，wait(long timeout, long nanos)，调用wait方法后，该线程放弃监视资源的所有权进入等待状态；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait()：等待有其它的线程调用notify()或notifyAll()进入调度状态，与其它线程共同争夺监视。wait()相当于wait(0)，wait(0, 0)。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait(long timeout)：当其它线程调用notify()或notifyAll()，或时间到达timeout亳秒，或有其它某线程中断该线程，则该线程进入调度状态。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wait(long timeout, long nanos)：相当于wait(1000000*timeout + nanos)，只不过时间单位为纳秒。<br />
<br />
<br />
<br />
<font color="#ff0000" size="3"><strong>线程池：</strong></font><br />
&nbsp;&nbsp;&nbsp; 多线程技术主要解决处理器单元内多个线程执行的问题，它可以显著减少处理器单元的闲置时间，增加处理器单元的吞吐能力。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 假设一个服务器完成一项任务所需时间为：T1 创建线程时间，T2 在线程中执行任务的时间，T3 销毁线程时间。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 如果：T1 + T3 远大于 T2，则可以采用线程池，以提高服务器性能。<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; 1、线程池管理器（ThreadPool）：用于创建并管理线程池，包括 创建线程池，销毁线程池，添加新任务；<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 2、工作线程（PoolWorker）：线程池中线程，在没有任务时处于等待状态，可以循环的执行任务；<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 3、任务接口（Task）：每个任务必须实现的接口，以供工作线程调度任务的执行，它主要规定了任务的入口，任务执行完后的收尾工作，任务的执行状态等；<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 4、任务队列（taskQueue）：用于存放没有处理的任务。提供一种缓冲机制。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 线程池技术正是关注如何缩短或调整T1,T3时间的技术，从而提高服务器程序性能的。它把T1，T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段，这样在服务器程序处理客户请求时，不会有T1，T3的开销了。<br />
<br />
&nbsp;&nbsp;&nbsp; 线程池不仅调整T1,T3产生的时间段，而且它还显著减少了创建线程的数目，看一个例子：<br />
<br />
&nbsp;&nbsp;&nbsp; 假设一个服务器一天要处理50000个请求，并且每个请求需要一个单独的线程完成。在线程池中，线程数一般是固定的，所以产生线程总数不会超过线程池中线程的数目，而如果服务器不利用线程池来处理这些请求则线程总数为50000。一般线程池大小是远小于50000。所以利用线程池的服务器程序不会为了创建50000而在处理请求时浪费时间，从而提高效率。<br />
<br />
<br />
<strong>/** 线程池类，工作线程作为其内部类 **/</strong><br />
<br />
package org.ymcn.util;<br />
<br />
import java.util.Collections;<br />
import java.util.Date;<br />
import java.util.LinkedList;<br />
import java.util.List;<br />
<br />
import org.apache.log4j.Logger;<br />
<br />
/**<br />
* 线程池<br />
* 创建线程池，销毁线程池，添加新任务<br />
* <br />
* @author obullxl<br />
*/<br />
public final class ThreadPool {<br />
&nbsp;&nbsp;&nbsp; private static Logger logger = Logger.getLogger(ThreadPool.class);<br />
&nbsp;&nbsp;&nbsp; private static Logger taskLogger = Logger.getLogger("TaskLogger");<br />
<br />
&nbsp;&nbsp;&nbsp; private static boolean debug = taskLogger.isDebugEnabled();<br />
&nbsp;&nbsp;&nbsp; // private static boolean debug = taskLogger.isInfoEnabled();<br />
&nbsp;&nbsp;&nbsp; /* 单例 */<br />
&nbsp;&nbsp;&nbsp; private static ThreadPool instance = ThreadPool.getInstance();<br />
<br />
&nbsp;&nbsp;&nbsp; public static final int SYSTEM_BUSY_TASK_COUNT = 150;<br />
&nbsp;&nbsp;&nbsp; /* 默认池中线程数 */<br />
&nbsp;&nbsp;&nbsp; public static int worker_num = 5;<br />
&nbsp;&nbsp;&nbsp; /* 已经处理的任务数 */<br />
&nbsp;&nbsp;&nbsp; private static int taskCounter = 0;<br />
<br />
&nbsp;&nbsp;&nbsp; public static boolean systemIsBusy = false;<br />
<br />
&nbsp;&nbsp;&nbsp; private static List&lt;Task&gt; taskQueue = Collections<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .synchronizedList(new LinkedList&lt;Task&gt;());<br />
&nbsp;&nbsp;&nbsp; /* 池中的所有线程 */<br />
&nbsp;&nbsp;&nbsp; public PoolWorker[] workers;<br />
<br />
&nbsp;&nbsp;&nbsp; private ThreadPool() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; workers = new PoolWorker[5];<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; workers.length; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; workers[i] = new PoolWorker(i);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; private ThreadPool(int pool_worker_num) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; worker_num = pool_worker_num;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; workers = new PoolWorker[worker_num];<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; workers.length; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; workers[i] = new PoolWorker(i);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public static synchronized ThreadPool getInstance() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (instance == null)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return new ThreadPool();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return instance;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 增加新的任务<br />
&nbsp;&nbsp;&nbsp; * 每增加一个新任务，都要唤醒任务队列<br />
&nbsp;&nbsp;&nbsp; * @param newTask<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public void addTask(Task newTask) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; synchronized (taskQueue) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; newTask.setTaskId(++taskCounter);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; newTask.setSubmitTime(new Date());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; taskQueue.add(newTask);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* 唤醒队列, 开始执行 */<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; taskQueue.notifyAll();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; logger.info("Submit Task&lt;" + newTask.getTaskId() + "&gt;: "<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; + newTask.info());<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 批量增加新任务<br />
&nbsp;&nbsp;&nbsp; * @param taskes<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public void batchAddTask(Task[] taskes) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (taskes == null || taskes.length == 0) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; synchronized (taskQueue) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; taskes.length; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (taskes[i] == null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; continue;<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; taskes[i].setTaskId(++taskCounter);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; taskes[i].setSubmitTime(new Date());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; taskQueue.add(taskes[i]);<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; &nbsp;&nbsp;&nbsp; taskQueue.notifyAll();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; taskes.length; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (taskes[i] == null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; continue;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; logger.info("Submit Task&lt;" + taskes[i].getTaskId() + "&gt;: "<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; + taskes[i].info());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 线程池信息<br />
&nbsp;&nbsp;&nbsp; * @return<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public String getInfo() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; StringBuffer sb = new StringBuffer();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb.append("\nTask Queue Size:" + taskQueue.size());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; workers.length; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb.append("\nWorker " + i + " is "<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; + ((workers[i].isWaiting()) ? "Waiting." : "Running."));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return sb.toString();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 销毁线程池<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public synchronized void destroy() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; worker_num; i++) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; workers[i].stopWorker();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; workers[i] = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; taskQueue.clear();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 池中工作线程<br />
&nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp; * @author obullxl<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; private class PoolWorker extends Thread {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; private int index = -1;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* 该工作线程是否有效 */<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; private boolean isRunning = true;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* 该工作线程是否可以执行新任务 */<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; private boolean isWaiting = true;<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public PoolWorker(int index) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.index = index;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; start();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void stopWorker() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.isRunning = false;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public boolean isWaiting() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return this.isWaiting;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * 循环执行任务<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * 这也许是线程池的关键所在<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void run() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (isRunning) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Task r = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; synchronized (taskQueue) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (taskQueue.isEmpty()) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* 任务队列为空，则等待有新任务加入从而被唤醒 */<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; taskQueue.wait(20);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (InterruptedException ie) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; logger.error(ie);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<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; r = (Task) taskQueue.remove(0);<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; if (r != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; isWaiting = false;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (debug) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; r.setBeginExceuteTime(new Date());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; taskLogger.debug("Worker&lt;" + index<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; + "&gt; start execute Task&lt;" + r.getTaskId() + "&gt;");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (r.getBeginExceuteTime().getTime()<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; - r.getSubmitTime().getTime() &gt; 1000)<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; taskLogger.debug("longer waiting time. "<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; + r.info() + ",&lt;" + index + "&gt;,time:"<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; + (r.getFinishTime().getTime() - r<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; .getBeginExceuteTime().getTime()));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* 该任务是否需要立即执行 */<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (r.needExecuteImmediate()) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; new Thread(r).start();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; r.run();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (debug) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; r.setFinishTime(new Date());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; taskLogger.debug("Worker&lt;" + index<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; + "&gt; finish task&lt;" + r.getTaskId() + "&gt;");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (r.getFinishTime().getTime()<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; - r.getBeginExceuteTime().getTime() &gt; 1000)<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; taskLogger.debug("longer execution time. "<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; + r.info() + ",&lt;" + index + "&gt;,time:"<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; + (r.getFinishTime().getTime() - r<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; .getBeginExceuteTime().getTime()));<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; logger.error(e);<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; isWaiting = true;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; r = null;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
<strong>/** 任务接口类 **/</strong><br />
<br />
package org.ymcn.util;<br />
<br />
import java.util.Date;<br />
<br />
/**<br />
* 所有任务接口<br />
* 其他任务必须继承访类<br />
* <br />
* @author obullxl<br />
*/<br />
public abstract class Task implements Runnable {<br />
&nbsp;&nbsp;&nbsp; // private static Logger logger = Logger.getLogger(Task.class);<br />
&nbsp;&nbsp;&nbsp; /* 产生时间 */<br />
&nbsp;&nbsp;&nbsp; private Date generateTime = null;<br />
&nbsp;&nbsp;&nbsp; /* 提交执行时间 */<br />
&nbsp;&nbsp;&nbsp; private Date submitTime = null;<br />
&nbsp;&nbsp;&nbsp; /* 开始执行时间 */<br />
&nbsp;&nbsp;&nbsp; private Date beginExceuteTime = null;<br />
&nbsp;&nbsp;&nbsp; /* 执行完成时间 */<br />
&nbsp;&nbsp;&nbsp; private Date finishTime = null;<br />
<br />
&nbsp;&nbsp;&nbsp; private long taskId;<br />
<br />
&nbsp;&nbsp;&nbsp; public Task() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.generateTime = new Date();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 任务执行入口<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public void run() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * 相关执行代码<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * beginTransaction();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * 执行过程中可能产生新的任务 subtask = taskCore();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * commitTransaction();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * 增加新产生的任务 ThreadPool.getInstance().batchAddTask(taskCore());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 所有任务的核心 所以特别的业务逻辑执行之处<br />
&nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp; * @throws Exception<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public abstract Task[] taskCore() throws Exception;<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 是否用到数据库<br />
&nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp; * @return<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; protected abstract boolean useDb();<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 是否需要立即执行<br />
&nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp; * @return<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; protected abstract boolean needExecuteImmediate();<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; * 任务信息<br />
&nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp; * @return String<br />
&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public abstract String info();<br />
<br />
&nbsp;&nbsp;&nbsp; public Date getGenerateTime() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return generateTime;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public Date getBeginExceuteTime() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return beginExceuteTime;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public void setBeginExceuteTime(Date beginExceuteTime) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.beginExceuteTime = beginExceuteTime;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public Date getFinishTime() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return finishTime;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public void setFinishTime(Date finishTime) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.finishTime = finishTime;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public Date getSubmitTime() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return submitTime;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public void setSubmitTime(Date submitTime) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.submitTime = submitTime;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public long getTaskId() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return taskId;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public void setTaskId(long taskId) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.taskId = taskId;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
}<br />
<br />
<br />
<br />
<a href="http://hi.baidu.com/obullxl/blog/item/ee50ad1ba8e8ff1f8718bf66.html">转自：http://hi.baidu.com/obullxl/blog/item/ee50ad1ba8e8ff1f8718bf66.html</a> 
<img src ="http://www.blogjava.net/standlww/aggbug/235100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2008-10-17 23:20 <a href="http://www.blogjava.net/standlww/archive/2008/10/17/235100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正则表达式简单教程</title><link>http://www.blogjava.net/standlww/archive/2008/10/06/232748.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Mon, 06 Oct 2008 12:12:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2008/10/06/232748.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/232748.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2008/10/06/232748.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/232748.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/232748.html</trackback:ping><description><![CDATA[<h2 class="title">正则表达式系统教程</h2>
<p class="postdate"><a href="http://www.kalvin.cn/?action=index&amp;cid=2"></a>&nbsp;</p>
<div class="content">
<p><strong>1. 引子<br />
</strong>　　目前，正则表达式已经在很多软件中得到广泛的应用，包括*nix（Linux, Unix等），HP等操作系统，PHP，C#，Java等开发环境，以及很多的应用软件中，都可以看到正则表达式的影子。<br />
<br />
　　正则表达式的使用，可以通过简单的办法来实现强大的功能。为了简单有效而又不失强大，造成了正则表达式代码的难度较大，学习起来也不是很容易，所以需要付出一些努力才行，入门之后参照一定的参考，使用起来还是比较简单有效的。<br />
<br />
　　例子： ^.+@.+\\..+$ <br />
<br />
　　这样的代码曾经多次把我自己给吓退过。可能很多人也是被这样的代码给吓跑的吧。继续阅读本文将让你也可以自由应用这样的代码。<br />
<br />
　　注意：这里的第7部分跟前面的内容看起来似乎有些重复，目的是把前面表格里的部分重新描述了一次，目的是让这些内容更容易理解。<br />
<br />
<br />
<strong>2. 正则表达式的历史<br />
<br />
</strong>　　正则表达式的&#8220;祖先&#8221;可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。<br />
<br />
　　1956 年, 一位叫 Stephen Kleene 的数学家在 McCulloch 和 Pitts 早期工作的基础上，发表了一篇标题为&#8220;神经网事件的表示法&#8221;的论文，引入了正则表达式的概念。正则表达式就是用来描述他称为&#8220;正则集的代数&#8221;的表达式，因此采用&#8220;正则表达式&#8221;这个术语。<br />
<br />
　　随后，发现可以将这一工作应用于使用 Ken Thompson 的计算搜索算法的一些早期研究，Ken Thompson 是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。<br />
<br />
　　如他们所说，剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。<br />
<br />
<strong>3. 正则表达式定义<br />
<br />
</strong>　　正则表达式(regular expression)描述了一种字符串匹配的模式，可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。<br />
<br />
　　列目录时，　dir *.txt或ls *.txt中的*.txt就不是一个正则表达式,因为这里*与正则式的*的含义是不同的。 <br />
<br />
　　正则表达式是由普通字符（例如字符 a 到 z）以及特殊字符（称为元字符）组成的文字模式。正则表达式作为一个模板，将某个字符模式与所搜索的字符串进行匹配。<br />
<a name="31"></a><br />
　　3.1 普通字符<br />
<br />
　　由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符，所有数字，所有标点符号以及一些符号。 <br />
<a name="32"></a><br />
　　3.2 非打印字符<br />
<br />
<table cellspacing="1" cellpadding="3" align="center" bgcolor="#eaeaea" border="0">
    <tbody>
        <tr bgcolor="#f0f0f0">
            <th style="font-size: 12px" align="left">字符 </th>
            <th style="font-size: 12px" align="left">含义</th>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px" width="40">\cx </td>
            <td style="font-size: 12px">匹配由x指明的控制字符。例如， \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则，将 c 视为一个原义的 'c' 字符。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\f </td>
            <td style="font-size: 12px">匹配一个换页符。等价于 \x0c 和 \cL。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\n </td>
            <td style="font-size: 12px">匹配一个换行符。等价于 \x0a 和 \cJ。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\r </td>
            <td style="font-size: 12px">匹配一个回车符。等价于 \x0d 和 \cM。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\s </td>
            <td style="font-size: 12px">匹配任何空白字符，包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\S </td>
            <td style="font-size: 12px">匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\t </td>
            <td style="font-size: 12px">匹配一个制表符。等价于 \x09 和 \cI。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\v </td>
            <td style="font-size: 12px">匹配一个垂直制表符。等价于 \x0b 和 \cK。</td>
        </tr>
    </tbody>
</table>
<br />
<a name="33"></a>　<br />
　　3.3 特殊字符<br />
<br />
　　所谓特殊字符，就是一些有特殊含义的字符，如上面说的"*.txt"中的*，简单的说就是表示任何字符串的意思。如果要查找文件名中有＊的文件，则需要对＊进行转义，即在其前加一个\。ls \*.txt。正则表达式有以下特殊字符。<br />
<br />
<table cellspacing="1" cellpadding="3" align="center" bgcolor="#eaeaea" border="0">
    <tbody>
        <tr bgcolor="#f0f0f0">
            <th style="font-size: 12px" align="left" width="60">特别字符</th>
            <th style="font-size: 12px" align="left">说明</th>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">$</td>
            <td style="font-size: 12px">匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性，则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身，请使用 \$。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">( )</td>
            <td style="font-size: 12px">标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符，请使用 \( 和 \)。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">*</td>
            <td style="font-size: 12px">匹配前面的子表达式零次或多次。要匹配 * 字符，请使用 \*。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">+</td>
            <td style="font-size: 12px">匹配前面的子表达式一次或多次。要匹配 + 字符，请使用 \+。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">.</td>
            <td style="font-size: 12px">匹配除换行符 \n之外的任何单字符。要匹配 .，请使用 \。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">[ </td>
            <td style="font-size: 12px">标记一个中括号表达式的开始。要匹配 [，请使用 \[。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">?</td>
            <td style="font-size: 12px">匹配前面的子表达式零次或一次，或指明一个非贪婪限定符。要匹配 ? 字符，请使用 \?。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\</td>
            <td style="font-size: 12px">将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如， 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\"，而 '\(' 则匹配 "("。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">^</td>
            <td style="font-size: 12px">匹配输入字符串的开始位置，除非在方括号表达式中使用，此时它表示不接受该字符集合。要匹配 ^ 字符本身，请使用 \^。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">{</td>
            <td style="font-size: 12px">标记限定符表达式的开始。要匹配 {，请使用 \{。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">|</td>
            <td style="font-size: 12px">指明两项之间的一个选择。要匹配 |，请使用 \|。</td>
        </tr>
    </tbody>
</table>
　<br />
<br />
　　构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。 <br />
　<br />
<a name="34"></a><br />
　　3.4 限定符<br />
<br />
　　限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{n,m}共6种。<br />
<br />
　　*、+和?限定符都是贪婪的，因为它们会尽可能多的匹配文字，只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。<br />
<br />
　　正则表达式的限定符有：<br />
<br />
<table cellspacing="1" cellpadding="3" align="center" bgcolor="#eaeaea" border="0">
    <tbody>
        <tr bgcolor="#f0f0f0">
            <th style="font-size: 12px" align="left" width="40">字符 </th>
            <th style="font-size: 12px" align="left">描述</th>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">* </td>
            <td style="font-size: 12px">匹配前面的子表达式零次或多次。例如，zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">+ </td>
            <td style="font-size: 12px">匹配前面的子表达式一次或多次。例如，'zo+' 能匹配 "zo" 以及 "zoo"，但不能匹配 "z"。+ 等价于 {1,}。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">? </td>
            <td style="font-size: 12px">匹配前面的子表达式零次或一次。例如，"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">{n} </td>
            <td style="font-size: 12px">n 是一个非负整数。匹配确定的 n 次。例如，'o{2}' 不能匹配 "Bob" 中的 'o'，但是能匹配 "food" 中的两个 o。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">{n,} </td>
            <td style="font-size: 12px">n 是一个非负整数。至少匹配n 次。例如，'o{2,}' 不能匹配 "Bob" 中的 'o'，但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">{n,m} </td>
            <td style="font-size: 12px">m 和 n 均为非负整数，其中n &lt;= m。最少匹配 n 次且最多匹配 m 次。例如，"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。</td>
        </tr>
    </tbody>
</table>
<br />
<a name="35"></a><br />
　　<strong>3.5 定位符</strong><br />
<br />
　　用来描述字符串或单词的边界，^和$分别指字符串的开始与结束，\b描述单词的前或后边界，\B表示非单词边界。<span style="color: #ff0000">不能对定位符使用限定符。 </span><br />
<a name="36"></a><br />
　　3.6 选择<br />
<br />
　　用圆括号将所有选择项括起来，相邻的选择项之间用|分隔。但用圆括号会有一个副作用，是相关的匹配会被缓存，此时可用?:放在第一个选项前来消除这种副作用。<br />
<br />
　　其中?:是非捕获元之一，还有两个非捕获元是?=和?!，这两个还有更多的含义，前者为正向预查，在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串，后者为负向预查，在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。 <br />
<a name="37"></a><br />
　　3.7 后向引用<br />
<br />
　　对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中，所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始，连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '\n' 访问，其中 n 为一个标识特定缓冲区的一位或两位十进制数。<br />
<br />
　　可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对相关匹配的保存。 <br />
<br />
<br />
<strong>4. 各种操作符的运算优先级<br />
<br />
</strong>　　相同优先级的从左到右进行运算，不同优先级的运算先高后低。各种操作符的优先级从高到低如下：<br />
<br />
<table cellspacing="1" cellpadding="3" align="center" bgcolor="#eaeaea" border="0">
    <tbody>
        <tr bgcolor="#f0f0f0">
            <th style="font-size: 12px" align="left" width="200" bgcolor="#f0f0f0">操作符 </th>
            <th style="font-size: 12px" align="left">描述</th>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\ </td>
            <td style="font-size: 12px">转义符</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">(), (?:), (?=), [] </td>
            <td style="font-size: 12px">圆括号和方括号</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">*, +, ?, {n}, {n,}, {n,m} </td>
            <td style="font-size: 12px">限定符</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">^, $, \anymetacharacter </td>
            <td style="font-size: 12px">位置和顺序</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">| </td>
            <td style="font-size: 12px">&#8220;或&#8221;操作</td>
        </tr>
    </tbody>
</table>
</p>
<p><strong>5. 全部符号解释<br />
<br />
</strong>
<table cellspacing="1" cellpadding="3" align="center" bgcolor="#eaeaea" border="0">
    <tbody>
        <tr bgcolor="#f0f0f0">
            <th style="font-size: 12px" align="left" width="80" bgcolor="#f0f0f0">字符 </th>
            <th style="font-size: 12px" align="left">描述</th>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\ </td>
            <td style="font-size: 12px">将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如，'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">^ </td>
            <td style="font-size: 12px">匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性，^ 也匹配 '\n' 或 '\r' 之后的位置。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">$ </td>
            <td style="font-size: 12px">匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性，$ 也匹配 '\n' 或 '\r' 之前的位置。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">* </td>
            <td style="font-size: 12px">匹配前面的子表达式零次或多次。例如，zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">+ </td>
            <td style="font-size: 12px">匹配前面的子表达式一次或多次。例如，'zo+' 能匹配 "zo" 以及 "zoo"，但不能匹配 "z"。+ 等价于 {1,}。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">? </td>
            <td style="font-size: 12px">匹配前面的子表达式零次或一次。例如，"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">{n} </td>
            <td style="font-size: 12px">n 是一个非负整数。匹配确定的 n 次。例如，'o{2}' 不能匹配 "Bob" 中的 'o'，但是能匹配 "food" 中的两个 o。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">{n,} </td>
            <td style="font-size: 12px">n 是一个非负整数。至少匹配n 次。例如，'o{2,}' 不能匹配 "Bob" 中的 'o'，但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">{n,m} </td>
            <td style="font-size: 12px">m 和 n 均为非负整数，其中n &lt;= m。最少匹配 n 次且最多匹配 m 次。例如，"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">? </td>
            <td style="font-size: 12px">当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时，匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串，而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如，对于字符串 "oooo"，'o+?' 将匹配单个 "o"，而 'o+' 将匹配所有 'o'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">. </td>
            <td style="font-size: 12px">匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符，请使用象 '[.\n]' 的模式。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">(pattern) </td>
            <td style="font-size: 12px">匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到，在VBScript 中使用 SubMatches 集合，在JScript 中则使用 $0&#8230;$9 属性。要匹配圆括号字符，请使用 '\(' 或 '\)'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">(?:pattern) </td>
            <td style="font-size: 12px">匹配 pattern 但不获取匹配结果，也就是说这是一个非获取匹配，不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如， 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">(?=pattern) </td>
            <td style="font-size: 12px">正向预查，在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如，'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ，但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">(?!pattern) </td>
            <td style="font-size: 12px">负向预查，在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows"，但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之后开始</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">x|y </td>
            <td style="font-size: 12px">匹配 x 或 y。例如，'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">[xyz] </td>
            <td style="font-size: 12px">字符集合。匹配所包含的任意一个字符。例如， '[abc]' 可以匹配 "plain" 中的 'a'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">[^xyz] </td>
            <td style="font-size: 12px">负值字符集合。匹配未包含的任意字符。例如， '[^abc]' 可以匹配 "plain" 中的'p'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">[a-z] </td>
            <td style="font-size: 12px">字符范围。匹配指定范围内的任意字符。例如，'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">[^a-z] </td>
            <td style="font-size: 12px">负值字符范围。匹配任何不在指定范围内的任意字符。例如，'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\b </td>
            <td style="font-size: 12px">匹配一个单词边界，也就是指单词和空格间的位置。例如， 'er\b' 可以匹配"never" 中的 'er'，但不能匹配 "verb" 中的 'er'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\B </td>
            <td style="font-size: 12px">匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er'，但不能匹配 "never" 中的 'er'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\cx </td>
            <td style="font-size: 12px">匹配由 x 指明的控制字符。例如， \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则，将 c 视为一个原义的 'c' 字符。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\d </td>
            <td style="font-size: 12px">匹配一个数字字符。等价于 [0-9]。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\D </td>
            <td style="font-size: 12px">匹配一个非数字字符。等价于 [^0-9]。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\f </td>
            <td style="font-size: 12px">匹配一个换页符。等价于 \x0c 和 \cL。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\n </td>
            <td style="font-size: 12px">匹配一个换行符。等价于 \x0a 和 \cJ。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\r </td>
            <td style="font-size: 12px">匹配一个回车符。等价于 \x0d 和 \cM。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\s </td>
            <td style="font-size: 12px">匹配任何空白字符，包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\S </td>
            <td style="font-size: 12px">匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\t </td>
            <td style="font-size: 12px">匹配一个制表符。等价于 \x09 和 \cI。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\v </td>
            <td style="font-size: 12px">匹配一个垂直制表符。等价于 \x0b 和 \cK。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\w </td>
            <td style="font-size: 12px">匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\W </td>
            <td style="font-size: 12px">匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\xn </td>
            <td style="font-size: 12px">匹配 n，其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如，'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' &amp; "1"。正则表达式中可以使用 ASCII 编码。.</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\num </td>
            <td style="font-size: 12px">匹配 num，其中 num 是一个正整数。对所获取的匹配的引用。例如，'(.)\1' 匹配两个连续的相同字符。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\n </td>
            <td style="font-size: 12px">标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式，则 n 为向后引用。否则，如果 n 为八进制数字 (0-7)，则 n 为一个八进制转义值。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\nm </td>
            <td style="font-size: 12px">标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式，则 nm 为向后引用。如果 \nm 之前至少有 n 个获取，则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足，若 n 和 m 均为八进制数字 (0-7)，则 \nm 将匹配八进制转义值 nm。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\nml </td>
            <td style="font-size: 12px">如果 n 为八进制数字 (0-3)，且 m 和 l 均为八进制数字 (0-7)，则匹配八进制转义值 nml。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">\un </td>
            <td style="font-size: 12px">匹配 n，其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如， \u00A9 匹配版权符号 (?)。</td>
        </tr>
    </tbody>
</table>
</p>
<p><strong>6. 部分例子<br />
<br />
</strong>
<table cellspacing="1" cellpadding="3" align="center" bgcolor="#eaeaea" border="0">
    <tbody>
        <tr bgcolor="#f0f0f0">
            <th style="font-size: 12px" align="left" width="250" bgcolor="#f0f0f0">正则表达式</th>
            <th style="font-size: 12px" align="left">说明</th>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">/\b([a-z]+) \1\b/gi</td>
            <td style="font-size: 12px">一个单词连续出现的位置</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ </td>
            <td style="font-size: 12px">将一个URL解析为协议、域、端口及相对路径</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">/^(?:Chapter|Section) [1-9][0-9]{0,1}$/</td>
            <td style="font-size: 12px">定位章节的位置</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">/[-a-z]/</td>
            <td style="font-size: 12px">A至z共26个字母再加一个-号。</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">/ter\b/</td>
            <td style="font-size: 12px">可匹配chapter，而不能terminal</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">/\Bapt/</td>
            <td style="font-size: 12px">可匹配chapter，而不能aptitude</td>
        </tr>
        <tr bgcolor="#fafafa">
            <td style="font-size: 12px">/Windows(?=95 |98 |NT )/</td>
            <td style="font-size: 12px">可匹配Windows95或Windows98或WindowsNT,当找到一个匹配后，从Windows后面开始进行下一次的检索匹配。</td>
        </tr>
    </tbody>
</table>
　<br />
<strong>7. 正则表达式匹配规则<br />
</strong><a name="71"></a><br />
　　7.1 基本模式匹配<br />
<br />
　　一切从最基本的开始。模式，是正规表达式最基本的元素，它们是一组描述字符串特征的字符。模式可以很简单，由普通的字符串组成，也可以非常复杂，往往用特殊的字符表示一个范围内的字符、重复出现，或表示上下文。例如：<br />
<br />
　　^once <br />
<br />
　　这个模式包含一个特殊的字符^，表示该模式只匹配那些以once开头的字符串。例如该模式与字符串"once upon a time"匹配，与"There once was a man from NewYork"不匹配。正如如^符号表示开头一样，$符号用来匹配那些以给定模式结尾的字符串。<br />
<br />
　　bucket$ <br />
<br />
　　这个模式与"Who kept all of this cash in a bucket"匹配，与"buckets"不匹配。字符^和$同时使用时，表示精确匹配（字符串与模式一样）。例如：<br />
<br />
　　^bucket$ <br />
<br />
　　只匹配字符串"bucket"。如果一个模式不包括^和$，那么它与任何包含该模式的字符串匹配。例如：模式<br />
<br />
　　once <br />
<br />
　　与字符串<br />
<br />
　　There once was a man from NewYork<br />
　　Who kept all of his cash in a bucket.<br />
<br />
　　是匹配的。<br />
<br />
　　在该模式中的字母(o-n-c-e)是字面的字符，也就是说，他们表示该字母本身，数字也是一样的。其他一些稍微复杂的字符，如标点符号和白字符（空格、制表符等），要用到转义序列。所有的转义序列都用反斜杠(\)打头。制表符的转义序列是：\t。所以如果我们要检测一个字符串是否以制表符开头，可以用这个模式：<br />
<br />
　　^\t <br />
<br />
　　类似的，用\n表示&#8220;新行&#8221;，\r表示回车。其他的特殊符号，可以用在前面加上反斜杠，如反斜杠本身用\\表示，句号.用\.表示，以此类推。<br />
<a name="72"></a><br />
　　7.2 字符簇<br />
<br />
　　在INTERNET的程序中，正规表达式通常用来验证用户的输入。当用户提交一个FORM以后，要判断输入的电话号码、地址、EMAIL地址、信用卡号码等是否有效，用普通的基于字面的字符是不够的。<br />
<br />
　　所以要用一种更自由的描述我们要的模式的办法，它就是字符簇。要建立一个表示所有元音字符的字符簇，就把所有的元音字符放在一个方括号里：<br />
<br />
　　[AaEeIiOoUu] <br />
<br />
　　这个模式与任何元音字符匹配，但只能表示一个字符。用连字号可以表示一个字符的范围，如：<br />
<br />
　　[a-z] //匹配所有的小写字母 <br />
　　[A-Z] //匹配所有的大写字母 <br />
　　[a-zA-Z] //匹配所有的字母 <br />
　　[0-9] //匹配所有的数字 <br />
　　[0-9\.\-] //匹配所有的数字，句号和减号 <br />
　　[ \f\r\t\n] //匹配所有的白字符 <br />
<br />
　　同样的，这些也只表示一个字符，这是一个非常重要的。如果要匹配一个由一个小写字母和一位数字组成的字符串，比如"z2"、"t6"或"g7"，但不是"ab2"、"r2d3" 或"b52"的话，用这个模式：<br />
<br />
　　^[a-z][0-9]$ <br />
<br />
　　尽管[a-z]代表26个字母的范围，但在这里它只能与第一个字符是小写字母的字符串匹配。<br />
<br />
　　前面曾经提到^表示字符串的开头，但它还有另外一个含义。当在一组方括号里使用^是，它表示&#8220;非&#8221;或&#8220;排除&#8221;的意思，常常用来剔除某个字符。还用前面的例子，我们要求第一个字符不能是数字：<br />
<br />
　　^[^0-9][0-9]$ <br />
<br />
　　这个模式与"&amp;5"、"g7"及"-2"是匹配的，但与"12"、"66"是不匹配的。下面是几个排除特定字符的例子：<br />
<br />
　　[^a-z] //除了小写字母以外的所有字符 <br />
　　[^\\\/\^] //除了(\)(/)(^)之外的所有字符 <br />
　　[^\"\'] //除了双引号(")和单引号(')之外的所有字符 <br />
<br />
　　特殊字符"." (点，句号)在正规表达式中用来表示除了&#8220;新行&#8221;之外的所有字符。所以模式"^.5$"与任何两个字符的、以数字5结尾和以其他非&#8220;新行&#8221;字符开头的字符串匹配。模式"."可以匹配任何字符串，除了空串和只包括一个&#8220;新行&#8221;的字符串。<br />
<br />
　　PHP的正规表达式有一些内置的通用字符簇，列表如下：<br />
<br />
　　字符簇含义 <br />
<br />
　　[[:alpha:]] 任何字母 <br />
　　[[:digit:]] 任何数字 <br />
　　[[:alnum:]] 任何字母和数字 <br />
　　[[:space:]] 任何白字符 <br />
　　[[:upper:]] 任何大写字母 <br />
　　[[:lower:]] 任何小写字母 <br />
　　[[:punct:]] 任何标点符号 <br />
　　[[:xdigit:]] 任何16进制的数字，相当于[0-9a-fA-F] <br />
<a name="73"></a><br />
　　7.3 确定重复出现<br />
<br />
　　到现在为止，你已经知道如何去匹配一个字母或数字，但更多的情况下，可能要匹配一个单词或一组数字。一个单词有若干个字母组成，一组数字有若干个单数组成。跟在字符或字符簇后面的花括号({})用来确定前面的内容的重复出现的次数。 <br />
<br />
　　字符簇 含义 <br />
　　^[a-zA-Z_]$ 所有的字母和下划线 <br />
　　^[[:alpha:]]{3}$ 所有的3个字母的单词 <br />
　　^a$ 字母a <br />
　　^a{4}$ aaaa <br />
　　^a{2,4}$ aa,aaa或aaaa <br />
　　^a{1,3}$ a,aa或aaa <br />
　　^a{2,}$ 包含多于两个a的字符串 <br />
　　^a{2,} 如：aardvark和aaab，但apple不行 <br />
　　a{2,} 如：baad和aaa，但Nantucket不行 <br />
　　\t{2} 两个制表符 <br />
　　.{2} 所有的两个字符 <br />
<br />
　　这些例子描述了花括号的三种不同的用法。一个数字，{x}的意思是&#8220;前面的字符或字符簇只出现x次&#8221;；一个数字加逗号，{x,}的意思是&#8220;前面的内容出现x或更多的次数&#8221;；两个用逗号分隔的数字，{x,y}表示&#8220;前面的内容至少出现x次，但不超过y次&#8221;。我们可以把模式扩展到更多的单词或数字：<br />
<br />
　　^[a-zA-Z0-9_]{1,}$ //所有包含一个以上的字母、数字或下划线的字符串 <br />
　　^[0-9]{1,}$ //所有的正数 <br />
　　^\-{0,1}[0-9]{1,}$ //所有的整数 <br />
　　^\-{0,1}[0-9]{0,}\.{0,1}[0-9]{0,}$ //所有的小数 <br />
<br />
　　最后一个例子不太好理解，是吗？这么看吧：与所有以一个可选的负号(\-{0,1})开头(^)、跟着0个或更多的数字([0-9]{0,})、和一个可选的小数点(\.{0,1})再跟上0个或多个数字([0-9]{0,})，并且没有其他任何东西($)。下面你将知道能够使用的更为简单的方法。<br />
<br />
　　特殊字符"?"与{0,1}是相等的，它们都代表着：&#8220;0个或1个前面的内容&#8221;或&#8220;前面的内容是可选的&#8221;。所以刚才的例子可以简化为：<br />
<br />
　　^\-?[0-9]{0,}\.?[0-9]{0,}$ <br />
<br />
　　特殊字符"*"与{0,}是相等的，它们都代表着&#8220;0个或多个前面的内容&#8221;。最后，字符"+"与 {1,}是相等的，表示&#8220;1个或多个前面的内容&#8221;，所以上面的4个例子可以写成：<br />
<br />
　　^[a-zA-Z0-9_]+$ //所有包含一个以上的字母、数字或下划线的字符串 <br />
　　^[0-9]+$ //所有的正数 <br />
　　^\-?[0-9]+$ //所有的整数 <br />
　　^\-?[0-9]*\.?[0-9]*$ //所有的小数 <br />
<br />
　　当然这并不能从技术上降低正规表达式的复杂性，但可以使它们更容易阅读。</p>
</div>
<img src ="http://www.blogjava.net/standlww/aggbug/232748.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2008-10-06 20:12 <a href="http://www.blogjava.net/standlww/archive/2008/10/06/232748.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正则表达式(二)</title><link>http://www.blogjava.net/standlww/archive/2008/10/06/232745.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Mon, 06 Oct 2008 12:10:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2008/10/06/232745.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/232745.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2008/10/06/232745.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/232745.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/232745.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Regular Expressions (2) ---- Common Used Samples&nbsp;说明：以下所有的例子都在EditPad Pro下经过验证，如果不能用，可能和特定的解释引擎有关，稍稍修改就可以了。J（看得头都晕了~~）更多的例子：http://www.regexlib.com电子邮件验证简单验证电子邮件地址标准验证电子邮件地址数字验证大于零...&nbsp;&nbsp;<a href='http://www.blogjava.net/standlww/archive/2008/10/06/232745.html'>阅读全文</a><img src ="http://www.blogjava.net/standlww/aggbug/232745.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2008-10-06 20:10 <a href="http://www.blogjava.net/standlww/archive/2008/10/06/232745.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>索引文件构成</title><link>http://www.blogjava.net/standlww/archive/2008/09/23/230789.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Tue, 23 Sep 2008 15:58:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2008/09/23/230789.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/230789.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2008/09/23/230789.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/230789.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/230789.html</trackback:ping><description><![CDATA[<p style="line-height: 150%" align="left"><strong><font size="4">索引文件构成<br />
</font></strong><br />
<strong>1．索引文件</strong><br />
&nbsp;&nbsp;&nbsp; 　索引文件由主文件和索引表构成。<br />
　　①主文件：文件本身。<br />
　　②索引表：在文件本身外建立的一张表，它指明逻辑记录和物理记录之间的一一对应关系。<br />
<br />
<strong>2．索引表组成</strong><br />
&nbsp;&nbsp;&nbsp; 　索引表由若干索引项组成。一般索引项由主关键字和该关键字所在记录的物理地址组成。<br />
&nbsp; <font color="#ff0000">注意：</font><br />
　&nbsp;&nbsp;&nbsp; 索引表必须按主关键字有序，而主文件本身则可以按主关键字有序或无序。<br />
<font color="#ff0000"><br />
</font><strong>3．索引顺序文件和索引非顺序文件</strong><br />
<font color="#0000ff">（1）索引顺序文件(Indexed Sequential File)</font><br />
&nbsp;&nbsp;&nbsp; 　主文件按主关键字有序的文件称索引顺序文件。<br />
&nbsp;&nbsp;&nbsp; 　在索引顺序文件中，可对一组记录建立一个索引项。这种索引表称为稀疏索引。<br />
<br />
<font color="#0000ff">（2）索引非顺序文件(Indexed NonSequentail File)</font><br />
&nbsp;&nbsp;&nbsp; 　主文件按主关键字无序得文件称索引非顺序文件。<br />
&nbsp;&nbsp;&nbsp; 　在索引非顺序文件中，必须为每个记录建立一个索引项，这样建立的索引表称为稠密索引。<br />
&nbsp; <font color="#ff0000">注意：</font><br />
&nbsp;&nbsp;&nbsp; 　① 通常将索引非顺序文件简称为索引文件。<br />
&nbsp;&nbsp;&nbsp; 　② 索引非顺序文件主文件无序，顺序存取将会频繁地引起磁头移动，适合于随机存取，不适合于顺序存取。<br />
&nbsp;&nbsp;&nbsp; 　③ 索引顺序文件的主文件是有序的，适合于随机存取、顺序存取。<br />
&nbsp;&nbsp;&nbsp; 　④ 索引顺序文件的索引是稀疏索引。索引占用空间较少，是最常用的一种文件组织。<br />
&nbsp;&nbsp;&nbsp; 　⑤ 最常用的索引顺序文件：ISAM文件和VSAM文件。<br />
<font color="#008000" size="4"><br />
</font><font size="4"><strong>索引文件的存储<br />
</strong></font><br />
<strong>1．索引文件的存储</strong><br />
&nbsp;&nbsp;&nbsp;　 索引文件在存储器上分为两个区：索引区和数据区。索引区存放索引表，数据区存放主文件。<br />
<br />
<strong>2． 索引文件的建立</strong><br />
&nbsp;&nbsp;&nbsp; 　建立索引文件的过程：<br />
　　（1） 按输入记录的先后次序建立数据区和索引表。其中索引表中关键字是无序的<br />
　　（2） 待全部记录输入完毕后对索引表进行排序，排序后的索引表和主文件一起就形成了索引文件。<br />
　　【例】对于表10.2的数据文件，主关键字是职工号，排序前的索引表如表10.3所示，排序后的索引表见表10.4，表10.2和表10.4一起形成了一个索引文件。<br />
&nbsp;<br />
学习网址:<br />
http://student.zjzk.cn/course_ware/data_structure/web/wenjian/wenjian10.3.1.htm<br />
<center>
<p style="line-height: 150%">
<object codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0" height="200" width="500" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">
<param name="_cx" value="13229" /><param name="_cy" value="5292" /><param name="FlashVars" value="" /><param name="Movie" value="../IMAGE/b10.234.swf" /><param name="Src" value="../IMAGE/b10.234.swf" /><param name="WMode" value="Transparent" /><param name="Play" value="0" /><param name="Loop" value="-1" /><param name="Quality" value="High" /><param name="SAlign" value="" /><param name="Menu" value="-1" /><param name="Base" value="" /><param name="AllowScriptAccess" value="" /><param name="Scale" value="ShowAll" /><param name="DeviceFont" value="0" /><param name="EmbedMovie" value="0" /><param name="BGColor" value="" /><param name="SWRemote" value="" /><param name="MovieData" value="" /><param name="SeamlessTabbing" value="1" /><param name="Profile" value="0" /><param name="ProfileAddress" value="" /><param name="ProfilePort" value="0" /><param name="AllowNetworking" value="all" /><param name="AllowFullScreen" value="false" />
<embed src="../IMAGE/b10.234.swf" quality="high" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" width="500" height="200" wmode="transparent">                    </embed></object><br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </center></p>
<img src ="http://www.blogjava.net/standlww/aggbug/230789.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2008-09-23 23:58 <a href="http://www.blogjava.net/standlww/archive/2008/09/23/230789.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lucene 索引文件结构深入分析 </title><link>http://www.blogjava.net/standlww/archive/2008/09/23/230787.html</link><dc:creator>李威威</dc:creator><author>李威威</author><pubDate>Tue, 23 Sep 2008 15:54:00 GMT</pubDate><guid>http://www.blogjava.net/standlww/archive/2008/09/23/230787.html</guid><wfw:comment>http://www.blogjava.net/standlww/comments/230787.html</wfw:comment><comments>http://www.blogjava.net/standlww/archive/2008/09/23/230787.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/standlww/comments/commentRss/230787.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/standlww/services/trackbacks/230787.html</trackback:ping><description><![CDATA[<div class="excerpt">lucene索引文件结构分析在分析lucene的索引文件结构之前，我们先要理解反向索引（invertedindex）这个概念，反向索引是一种以索引项为中心来组织文档的方式，每个索引项指向一个文档序列，</div>
<!--div style="text-align:center;">
		</div-->
<div class="tbody">
<p><span><font face="arial" size="4">lucene 索引文件结构分析</font> </span></p>
<p>在分析 lucene 的索引文件结构之前，我们先要理解反向索引（inverted index）这个概念，反向索引是一种以索引项为中心来组织文档的方式，每个索引项指向一个文档序列，这个序列中的文档都包含该索引项。相反，在正向索引中，文档占据了中心的位置，每个文档指向了一个它所包含的索引项的序列。你可以利用反向索引轻松的找到那些文档包含了特定的索引项。lucene正是使用了反向索引作为其基本的索引结构。</p>
<p><span><font face="arial" size="4">索引文件的逻辑视图</font> </span></p>
<p>在lucene 中有索引块的概念，每个索引块包含了一定数目的文档。我们能够对单独的索引块进行检索。图 2 显示了 lucene 索引结构的逻辑视图。索引块的个数由索引的文档的总数以及每个索引块所能包含的最大文档数来决定。</p>
<p><br />
<strong>图2：索引文件的逻辑视图</strong>&nbsp;<br />
&nbsp;<img height="415" alt="" src="http://www.hbdev.cn/uploadfile/3/image004.jpg" width="467" /><br />
</p>
<p><span><font face="arial" size="4">lucene 中的关键索引文件</font> </span></p>
<p>下面的部分将会分析lucene中的主要的索引文件，可能分析有些索引文件的时候没有包含文件的所有的字段，但不会影响到对索引文件的理解。</p>
<p>1．索引块文件</p>
<p>这个文件包含了索引中的索引块信息，这个文件包含了每个索引块的名字以及大小等信息。表 2 显示了这个文件的结构信息。</p>
<p><br />
<strong>表2：索引块文件结构</strong>&nbsp;<br />
<img height="198" alt="" src="http://www.hbdev.cn/uploadfile/3/table2.gif" width="568" /><br />
</p>
<p>2．域信息文件</p>
<p>我们知道，索引中的文档由一个或者多个域组成，这个文件包含了每个索引块中的域的信息。表 3 显示了这个文件的结构。</p>
<p><br />
<strong>表3：域信息文件结构</strong>&nbsp;<br />
<img height="179" alt="" src="http://www.hbdev.cn/uploadfile/3/table3.gif" width="567" /><br />
</p>
<p>3．索引项信息文件</p>
<p>这是索引文件里面最核心的一个文件，它存储了所有的索引项的值以及相关信息，并且以索引项来排序。表 4 显示了这个文件的结构。</p>
<p><br />
<strong>表4：索引项信息文件结构</strong>&nbsp;<br />
<img height="252" alt="" src="http://www.hbdev.cn/uploadfile/3/table4.gif" width="568" /><br />
</p>
<p>4．频率文件</p>
<p>这个文件包含了包含索引项的文档的列表，以及索引项在每个文档中出现的频率信息。如果lucene在索引项信息文件中发现有索引项和搜索词相匹配。那么 lucene 就会在频率文件中找有哪些文件包含了该索引项。表5显示了这个文件的一个大致的结构，并没有包含这个文件的所有字段。</p>
<p><br />
<strong>表5：频率文件的结构</strong>&nbsp;<br />
<img height="124" alt="" src="http://www.hbdev.cn/uploadfile/3/table5.gif" width="567" /><br />
</p>
<p>5．位置文件</p>
<p>这个文件包含了索引项在每个文档中出现的位置信息，你可以利用这些信息来参与对索引结果的排序。表 6 显示了这个文件的结构</p>
<p><br />
<strong>表6：位置文件的结构</strong>&nbsp;<br />
<span><font face="arial" size="4"><img height="69" alt="" src="http://www.hbdev.cn/uploadfile/3/table6.gif" width="568" /></font></span><br />
</p>
<p>到目前为止我们介绍了 lucene 中的主要的索引文件结构，希望能对你理解 lucene 的物理的存储结构有所帮助。</p>
</div>
<img src ="http://www.blogjava.net/standlww/aggbug/230787.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/standlww/" target="_blank">李威威</a> 2008-09-23 23:54 <a href="http://www.blogjava.net/standlww/archive/2008/09/23/230787.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>