﻿<?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-巨型诱饵的BLOG-文章分类-Java学习</title><link>http://www.blogjava.net/hugebait/category/9701.html</link><description>永无止境的Java的学习。</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 08:50:46 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 08:50:46 GMT</pubDate><ttl>60</ttl><item><title>JAVA5 多线程实践</title><link>http://www.blogjava.net/hugebait/articles/39949.html</link><dc:creator>巨型诱饵</dc:creator><author>巨型诱饵</author><pubDate>Sat, 08 Apr 2006 01:38:00 GMT</pubDate><guid>http://www.blogjava.net/hugebait/articles/39949.html</guid><wfw:comment>http://www.blogjava.net/hugebait/comments/39949.html</wfw:comment><comments>http://www.blogjava.net/hugebait/articles/39949.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hugebait/comments/commentRss/39949.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hugebait/services/trackbacks/39949.html</trackback:ping><description><![CDATA[转载自 健者天行的blog,原网址<a href="http://blog.csdn.net/chensheng913/archive/2006/02/06/592797.aspx">http://blog.csdn.net/chensheng913/archive/2006/02/06/592797.aspx</a><br /><br /><i><font color="#993300" size="2">Java5增加了新的类库并发集java.util.concurrent，该类库为并
发程序提供了丰富的API多线程编程在Java
5中更加容易，灵活。本文通过一个网络服务器模型，来实践Java5的多线程编程，该模型中使用了Java5中的线程池，阻塞队列，可重入锁等，还实践了
Callable， Future等接口，并使用了Java 5的另外一个新特性泛型。<br /><br /></font></i><p><font color="#993300" size="2">本文将实现一个网络服务器模型，一旦有客户端连接到该服务器，则启动一个新线程为该连接服务，服务内容为往客户端输送一些字符信息。一个典型的网络服务器模型如下：</font></p><p><font color="#993300" size="2">1. 建立监听端口。</font></p><p><font color="#993300" size="2">2. 发现有新连接，接受连接，启动线程，执行服务线程。</font></p><p><font color="#993300" size="2">3. 服务完毕，关闭线程。</font></p><p><font color="#993300" size="2">这个模型在大部分情况下运行良好，但是需要频繁的处理用户请求而每次请求需要的服
务又是简短的时候，系统会将大量的时间花费在线程的创建销毁。Java
5的线程池克服了这些缺点。通过对重用线程来执行多个任务，避免了频繁线程的创建与销毁开销，使得服务器的性能方面得到很大提高。因此，本文的网络服务器
模型将如下：</font></p><p><font color="#993300" size="2">1. 建立监听端口，创建线程池。</font></p><p><font color="#993300" size="2">2. 发现有新连接，使用线程池来执行服务任务。</font></p><p><font color="#993300" size="2">3. 服务完毕，释放线程到线程池。</font></p><p><font color="#993300" size="2">下面详细介绍如何使用Java 5的concurrent包提供的API来实现该服务器。</font></p><p><font color="#993300" size="2">初始化包括创建线程池以及初始化监听端口。创建线程池可以通过调用
java.util.concurrent.Executors类里的静态方法newChahedThreadPool或是
newFixedThreadPool来创建，也可以通过新建一个java.util.concurrent.ThreadPoolExecutor实例
来执行任务。这里我们采用newFixedThreadPool方法来建立线程池。</font></p><p><font size="2"><font color="#993300"><font face="Courier"><code>ExecutorService pool = Executors.newFixedThreadPool(10);</code><br /></font>表示新建了一个线程池，线程池里面有10个线程为任务队列服务。</font></font></p><p><font color="#993300" size="2">使用ServerSocket对象来初始化监听端口。<br /></font></p><p><font color="#993300" size="2"><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);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> PORT </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">19527</span><span style="color: rgb(0, 0, 0);">;<br />serverListenSocket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ServerSocket(PORT);<br />serverListenSocket.setReuseAddress(</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">);<br />serverListenSocket.setReuseAddress(</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">);</span></div><br /></font><font color="#993300" size="2">当有新连接建立时，accept返回时，将服务任务提交给线程池执行。<br /></font></p><p><font color="#993300" size="2"><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);">while</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">){<br />Socket socket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> serverListenSocket.accept();<br />pool.execute(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ServiceThread(socket));<br /><br />}</span></div><br /></font></p><p><font color="#993300" size="2">这里使用线程池对象来执行线程，减少了每次线程创建和销毁的开销。任务执行完毕，线程释放到线程池。</font></p><p> </p><p><font color="#993300" size="2">服务线程ServiceThread维护一个count来记录服务线程被调用的次
数。每当服务任务被调用一次时，count的值自增1，因此ServiceThread提供一个increaseCount和getCount的方法，分
别将count值自增1和取得该count值。由于可能多个线程存在竞争，同时访问count，因此需要加锁机制，在Java
5之前，我们只能使用synchronized来锁定。Java
5中引入了性能更加粒度更细的重入锁ReentrantLock。我们使用ReentrantLock保证代码线程安全。下面是具体代码：<br /></font></p><p><font color="#993300" size="2"><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);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> ReentrantLock lock </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ReentrantLock ();<br /></span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> count </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br /></span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> getCount(){<br />    </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> ret </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />    </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">{<br />        lock.lock();<br />        ret </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> count;<br />    }</span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);">{<br />        lock.unlock();<br />    }<br />    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> ret;<br />}    <br /></span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> increaseCount(){<br />    </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">{<br />        lock.lock();<br />        </span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">count;<br />    }</span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);">{<br />        lock.unlock();<br />    }<br />}</span></div><br /></font></p><p><font color="#993300" size="2">服务线程在开始给客户端打印一个欢迎信息，<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);">increaseCount();<br /></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> curCount </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> getCount();<br />helloString </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);">hello, id = </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);"> curCount</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\r\n</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />dos </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> DataOutputStream(connectedSocket.getOutputStream());<br />dos.write(helloString.getBytes());</span></div><br /></font><br /></p><p><font color="#993300" size="2">然后使用ExecutorService的submit方法提交一个
Callable的任务，返回一个Future接口的引用。这种做法对费时的任务非常有效，submit任务之后可以继续执行下面的代码，然后在适当的位
置可以使用Future的get方法来获取结果，如果这时候该方法已经执行完毕，则无需等待即可获得结果，如果还在执行，则等待到运行完毕。<br /></font></p><p><font color="#993300" size="2"><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);"><br />ExecutorService executor </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Executors.newSingleThreadExecutor();<br />Future </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">String</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> future </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> executor.submit(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> TimeConsumingTask());<br />dos.write(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">let's do soemthing other</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.getBytes());<br />String result </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> future.get();<br />dos.write(result.getBytes());<br />其中TimeConsumingTask实现了Callable接口<br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> TimeConsumingTask </span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);"> Callable </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">String</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">{<br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> String call() </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> Exception {<br />        System.out.println<br />        (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">It's a time-consuming task, </span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">        you</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">d better retrieve your result in the furture");</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">ok, here's the result: It takes me lots of time to produce this result</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />    }<br />}</span></div><br /></font></p><p><font color="#993300" size="2">这里使用了Java
5的另外一个新特性泛型，声明TimeConsumingTask的时候使用了String做为类型参数。必须实现Callable接口的call函数，
其作用类似与Runnable中的run函数，在call函数里写入要执行的代码，其返回值类型等同于在类声明中传入的类型值。在这段程序中，我们提交了
一个Callable的任务，然后程序不会堵塞，而是继续执行dos.write("let's do soemthing
other".getBytes());当程序执行到String result =
future.get()时如果call函数已经执行完毕，则取得返回值，如果还在执行，则等待其执行完毕。 </font></p><p><font color="#993300" size="2">服务器端的完整实现代码如下：<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);"> com.andrew;<br /><br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.io.DataOutputStream;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.io.IOException;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.io.Serializable;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.net.ServerSocket;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.net.Socket;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.ArrayBlockingQueue;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.BlockingQueue;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.Callable;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.ExecutionException;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.ExecutorService;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.Executors;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.Future;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.RejectedExecutionHandler;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.ThreadPoolExecutor;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.TimeUnit;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.concurrent.locks.ReentrantLock;<br /><br /></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);">class</span><span style="color: rgb(0, 0, 0);"> Server {<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> produceTaskSleepTime </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> consumeTaskSleepTime </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">1200</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> produceTaskMaxNumber </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> CORE_POOL_SIZE </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> MAX_POOL_SIZE </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> KEEPALIVE_TIME </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> QUEUE_CAPACITY </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (CORE_POOL_SIZE </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> MAX_POOL_SIZE) </span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> TimeUnit TIME_UNIT </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> TimeUnit.SECONDS;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> String HOST </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);">127.0.0.1</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> PORT </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">19527</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> BlockingQueue</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">Runnable</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> workQueue </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ArrayBlockingQueue</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">Runnable</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">(<br />            QUEUE_CAPACITY);<br /><br />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">private ThreadPoolExecutor serverThreadPool = null;</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">    <br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> ExecutorService pool </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> RejectedExecutionHandler rejectedExecutionHandler </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"><br />    ThreadPoolExecutor.DiscardOldestPolicy();<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> ServerSocket serverListenSocket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> times </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </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);">void</span><span style="color: rgb(0, 0, 0);"> start() {<br />        </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> You can also init thread pool in this way.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">        </span><span style="color: rgb(0, 128, 0);">/*</span><span style="color: rgb(0, 128, 0);">serverThreadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,<br />                MAX_POOL_SIZE, KEEPALIVE_TIME, TIME_UNIT, workQueue,<br />                rejectedExecutionHandler);</span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />        pool </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Executors.newFixedThreadPool(</span><span style="color: rgb(0, 0, 0);">10</span><span style="color: rgb(0, 0, 0);">);<br />        </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"> {<br />            serverListenSocket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ServerSocket(PORT);<br />            serverListenSocket.setReuseAddress(</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">);<br /><br />            System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">I'm listening</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />            </span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);"> (times</span><span style="color: rgb(0, 0, 0);">--</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">) {<br />                Socket socket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> serverListenSocket.accept();<br />                String welcomeString </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);">hello</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">serverThreadPool.execute(new ServiceThread(socket, welcomeString));</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">                pool.execute(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ServiceThread(socket));<br />            }<br />        } </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (IOException e) {<br />            </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> TODO Auto-generated catch block</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">            e.printStackTrace();<br />        }<br />        cleanup();<br />    }<br /><br />    </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);">void</span><span style="color: rgb(0, 0, 0);"> cleanup() {<br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);"> serverListenSocket) {<br />            </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"> {<br />                serverListenSocket.close();<br />            } </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (IOException e) {<br />                </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> TODO Auto-generated catch block</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">                e.printStackTrace();<br />            }<br />        }<br />        </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">serverThreadPool.shutdown();</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">        pool.shutdown();<br />    }<br /><br />    </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);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> main(String args[]) {<br />        Server server </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Server();<br />        server.start();<br />    }<br />}<br /><br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> ServiceThread </span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);"> Runnable, Serializable {<br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">final</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);"> serialVersionUID </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> Socket connectedSocket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> String helloString </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> count </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> ReentrantLock lock </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ReentrantLock();<br /><br />    ServiceThread(Socket socket) {<br />        connectedSocket </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> socket;<br />    }<br /><br />    </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);">void</span><span style="color: rgb(0, 0, 0);"> run() {<br />        increaseCount();<br />        </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> curCount </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> getCount();<br />        helloString </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);">hello, id = </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);"> curCount </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);">\r\n</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br /><br />        ExecutorService executor </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Executors.newSingleThreadExecutor();<br />        Future</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">String</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> future </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> executor.submit(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> TimeConsumingTask());<br /><br />        DataOutputStream dos </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br />        </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"> {<br />            dos </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> DataOutputStream(connectedSocket.getOutputStream());<br />            dos.write(helloString.getBytes());<br />            </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"> {<br />                dos.write(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">let's do soemthing other.\r\n</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.getBytes());<br />                String result </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> future.get();<br />                dos.write(result.getBytes());<br />            } </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (InterruptedException e) {<br />                e.printStackTrace();<br />            } </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (ExecutionException e) {<br />                e.printStackTrace();<br />            }<br />        } </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (IOException e) {<br />            </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> TODO Auto-generated catch block</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">            e.printStackTrace();<br />        } </span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);"> {<br />            </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);"> connectedSocket) {<br />                </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"> {<br />                    connectedSocket.close();<br />                } </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (IOException e) {<br />                    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> TODO Auto-generated catch block</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">                    e.printStackTrace();<br />                }<br />            }<br />            </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);"> dos) {<br />                </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"> {<br />                    dos.close();<br />                } </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (IOException e) {<br />                    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> TODO Auto-generated catch block</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">                    e.printStackTrace();<br />                }<br />            }<br />            executor.shutdown();<br />        }<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> getCount() {<br />        </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> ret </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />        </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"> {<br />            lock.lock();<br />            ret </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> count;<br />        } </span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);"> {<br />            lock.unlock();<br />        }<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> ret;<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> increaseCount() {<br />        </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"> {<br />            lock.lock();<br />            </span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">count;<br />        } </span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);"> {<br />            lock.unlock();<br />        }<br />    }<br />}<br /><br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> TimeConsumingTask </span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);"> Callable</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">String</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> {<br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> String call() </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> Exception {<br />        System.out<br />                .println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">It's a     time-consuming task, </span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">                you</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">d better retrieve your result in the furture");</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">ok, here's the result: It takes me lots of time to produce this result</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />    }<br /><br />}</span></div><br /></font><font color="#993300" size="2">运行服务端，客户端只需使用telnet 127.0.0.1 19527 即可看到信息如下：<br /></font></p><p><font color="#993300" size="2"><img src="http://www-128.ibm.com/developerworks/cn/java/j-zhanghz/images/image002.jpg" /><br /></font></p><p></p><img src ="http://www.blogjava.net/hugebait/aggbug/39949.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hugebait/" target="_blank">巨型诱饵</a> 2006-04-08 09:38 <a href="http://www.blogjava.net/hugebait/articles/39949.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>