﻿<?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-~~-文章分类-J2SE学习</title><link>http://www.blogjava.net/java-blog/category/26735.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 18 Apr 2008 13:53:51 GMT</lastBuildDate><pubDate>Fri, 18 Apr 2008 13:53:51 GMT</pubDate><ttl>60</ttl><item><title>java.util.concurrent 多线程框架</title><link>http://www.blogjava.net/java-blog/articles/193845.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Thu, 17 Apr 2008 11:11:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/193845.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/193845.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/193845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/193845.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/193845.html</trackback:ping><description><![CDATA[<br />
JDK5中的一个亮点就是将Doug Lea的并发库引入到Java标准库中。Doug Lea确实是一个牛人，能教书，能出书，能编码，不过这在国外还是比较普遍的，而国内的教授们就相差太远了。
<br />
<br />
一般的服务器都需要线程池，比如Web、FTP等服务器，不过它们一般都自己实现了线程池，比如以前介绍过的Tomcat、Resin和Jetty等，现在有了JDK5，我们就没有必要重复造车轮了，直接使用就可以，何况使用也很方便，性能也非常高。
<br />
<br />
<div>
<div>
<div>Java代码 <a href="http://daoger.javaeye.com/blog/142485#" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" title="复制代码"><img src="http://daoger.javaeye.com/images/icon_copy.gif" alt="复制代码" /></a></div>
</div>
<ol start="1">
    <li>package&nbsp;concurrent;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutorService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TestThreadPool&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[])&nbsp;throws&nbsp;InterruptedException&nbsp;{&nbsp;&nbsp;</li>
    <li>//&nbsp;only&nbsp;two&nbsp;threads&nbsp;&nbsp;</li>
    <li>ExecutorService&nbsp;exec&nbsp;=&nbsp;Executors.newFixedThreadPool(2);&nbsp;&nbsp;</li>
    <li>for(int&nbsp;index&nbsp;=&nbsp;0;&nbsp;index&nbsp;&lt;&nbsp;100;&nbsp;index++)&nbsp;{&nbsp;&nbsp;</li>
    <li>Runnable&nbsp;run&nbsp;=&nbsp;new&nbsp;Runnable()&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;void&nbsp;run()&nbsp;{&nbsp;&nbsp;</li>
    <li>long&nbsp;time&nbsp;=&nbsp;(long)&nbsp;(Math.random()&nbsp;*&nbsp;1000);&nbsp;&nbsp;</li>
    <li>System.out.println(&#8220;Sleeping&nbsp;&#8221;&nbsp;+&nbsp;time&nbsp;+&nbsp;&#8220;ms&#8221;);&nbsp;&nbsp;</li>
    <li>try&nbsp;{&nbsp;&nbsp;</li>
    <li>Thread.sleep(time);&nbsp;&nbsp;</li>
    <li>}&nbsp;catch&nbsp;(InterruptedException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>};&nbsp;&nbsp;</li>
    <li>exec.execute(run);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>//&nbsp;must&nbsp;shutdown&nbsp;&nbsp;</li>
    <li>exec.shutdown();&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestThreadPool {
public static void main(String args[]) throws InterruptedException {
// only two threads
ExecutorService exec = Executors.newFixedThreadPool(2);
for(int index = 0; index &lt; 100; index++) {
Runnable run = new Runnable() {
public void run() {
long time = (long) (Math.random() * 1000);
System.out.println(&#8220;Sleeping &#8221; + time + &#8220;ms&#8221;);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
}
}
};
exec.execute(run);
}
// must shutdown
exec.shutdown();
}
}
</pre>
<br />
上面是一个简单的例子，使用了2个大小的线程池来处理100个线程。但有一个问题：在for循环的过程中，会等待线程池有空闲的线程，所以主线程
会阻塞的。为了解决这个问题，一般启动一个线程来做for循环，就是为了避免由于线程池满了造成主线程阻塞。不过在这里我没有这样处理。[重要修正：经过
测试，即使线程池大小小于实际线程数大小，线程池也不会阻塞的，这与Tomcat的线程池不同，它将Runnable实例放到一个&#8220;无限&#8221;的
BlockingQueue中，所以就不用一个线程启动for循环，Doug Lea果然厉害]
<br />
<br />
另外它使用了Executors的静态函数生成一个固定的线程池，顾名思义，线程池的线程是不会释放的，即使它是Idle。这就会产生性能问题，
比如如果线程池的大小为200，当全部使用完毕后，所有的线程会继续留在池中，相应的内存和线程切换（while(true)+sleep循环）都会增
加。如果要避免这个问题，就必须直接使用ThreadPoolExecutor()来构造。可以像Tomcat的线程池一样设置&#8220;最大线程数&#8221;、&#8220;最小线
程数&#8221;和&#8220;空闲线程keepAlive的时间&#8221;。通过这些可以基本上替换Tomcat的线程池实现方案。
<br />
<br />
需要注意的是线程池必须使用shutdown来显式关闭，否则主线程就无法退出。shutdown也不会阻塞主线程。
<br />
<br />
许多长时间运行的应用有时候需要定时运行任务完成一些诸如统计、优化等工作，比如在电信行业中处理用户话单时，需要每隔1分钟处理话单；网站每天
凌晨统计用户访问量、用户数；大型超时凌晨3点统计当天销售额、以及最热卖的商品；每周日进行数据库备份；公司每个月的10号计算工资并进行转帐等，这些
都是定时任务。通过 java的并发库concurrent可以轻松的完成这些任务，而且非常的简单。
<br />
<br />
<div>
<div>
<div>Java代码 <a href="http://daoger.javaeye.com/blog/142485#" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" title="复制代码"><img src="http://daoger.javaeye.com/images/icon_copy.gif" alt="复制代码" /></a></div>
</div>
<ol start="1">
    <li>package&nbsp;concurrent;&nbsp;&nbsp;</li>
    <li>import&nbsp;static&nbsp;java.util.concurrent.TimeUnit.SECONDS;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.Date;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ScheduledExecutorService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ScheduledFuture;&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TestScheduledThread&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</li>
    <li>final&nbsp;ScheduledExecutorService&nbsp;scheduler&nbsp;=&nbsp;Executors&nbsp;&nbsp;</li>
    <li>.newScheduledThreadPool(2);&nbsp;&nbsp;</li>
    <li>final&nbsp;Runnable&nbsp;beeper&nbsp;=&nbsp;new&nbsp;Runnable()&nbsp;{&nbsp;&nbsp;</li>
    <li>int&nbsp;count&nbsp;=&nbsp;0;&nbsp;&nbsp;</li>
    <li>public&nbsp;void&nbsp;run()&nbsp;{&nbsp;&nbsp;</li>
    <li>System.out.println(new&nbsp;Date()&nbsp;+&nbsp;&#8221;&nbsp;beep&nbsp;&#8221;&nbsp;+&nbsp;(++count));&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>};&nbsp;&nbsp;</li>
    <li>//&nbsp;1秒钟后运行，并每隔2秒运行一次&nbsp;&nbsp;</li>
    <li>final&nbsp;ScheduledFuture&nbsp;beeperHandle&nbsp;=&nbsp;scheduler.scheduleAtFixedRate(&nbsp;&nbsp;</li>
    <li>beeper,&nbsp;1,&nbsp;2,&nbsp;SECONDS);&nbsp;&nbsp;</li>
    <li>//&nbsp;2秒钟后运行，并每次在上次任务运行完后等待5秒后重新运行&nbsp;&nbsp;</li>
    <li>final&nbsp;ScheduledFuture&nbsp;beeperHandle2&nbsp;=&nbsp;scheduler&nbsp;&nbsp;</li>
    <li>.scheduleWithFixedDelay(beeper,&nbsp;2,&nbsp;5,&nbsp;SECONDS);&nbsp;&nbsp;</li>
    <li>//&nbsp;30秒后结束关闭任务，并且关闭Scheduler&nbsp;&nbsp;</li>
    <li>scheduler.schedule(new&nbsp;Runnable()&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;void&nbsp;run()&nbsp;{&nbsp;&nbsp;</li>
    <li>beeperHandle.cancel(true);&nbsp;&nbsp;</li>
    <li>beeperHandle2.cancel(true);&nbsp;&nbsp;</li>
    <li>scheduler.shutdown();&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>},&nbsp;30,&nbsp;SECONDS);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package concurrent;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
public class TestScheduledThread {
public static void main(String[] args) {
final ScheduledExecutorService scheduler = Executors
.newScheduledThreadPool(2);
final Runnable beeper = new Runnable() {
int count = 0;
public void run() {
System.out.println(new Date() + &#8221; beep &#8221; + (++count));
}
};
// 1秒钟后运行，并每隔2秒运行一次
final ScheduledFuture beeperHandle = scheduler.scheduleAtFixedRate(
beeper, 1, 2, SECONDS);
// 2秒钟后运行，并每次在上次任务运行完后等待5秒后重新运行
final ScheduledFuture beeperHandle2 = scheduler
.scheduleWithFixedDelay(beeper, 2, 5, SECONDS);
// 30秒后结束关闭任务，并且关闭Scheduler
scheduler.schedule(new Runnable() {
public void run() {
beeperHandle.cancel(true);
beeperHandle2.cancel(true);
scheduler.shutdown();
}
}, 30, SECONDS);
}
}
</pre>
<br />
为了退出进程，上面的代码中加入了关闭Scheduler的操作。而对于24小时运行的应用而言，是没有必要关闭Scheduler的。
<br />
<br />
在实际应用中，有时候需要多个线程同时工作以完成同一件事情，而且在完成过程中，往往会等待其他线程都完成某一阶段后再执行，等所有线程都到达某一个阶段后再统一执行。
<br />
<br />
比如有几个旅行团需要途经深圳、广州、韶关、长沙最后到达武汉。旅行团中有自驾游的，有徒步的，有乘坐旅游大巴的；这些旅行团同时出发，并且每到一个目的地，都要等待其他旅行团到达此地后再同时出发，直到都到达终点站武汉。
<br />
<br />
这时候CyclicBarrier就可以派上用场。CyclicBarrier最重要的属性就是参与者个数，另外最要方法是await()。当所有线程都调用了await()后，就表示这些线程都可以继续执行，否则就会等待。
<br />
<div>
<div>
<div>Java代码 <a href="http://daoger.javaeye.com/blog/142485#" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" title="复制代码"><img src="http://daoger.javaeye.com/images/icon_copy.gif" alt="复制代码" /></a></div>
</div>
<ol start="1">
    <li>package&nbsp;concurrent;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.text.SimpleDateFormat;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.Date;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.BrokenBarrierException;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.CyclicBarrier;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutorService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TestCyclicBarrier&nbsp;{&nbsp;&nbsp;</li>
    <li>//&nbsp;徒步需要的时间:&nbsp;Shenzhen,&nbsp;Guangzhou,&nbsp;Shaoguan,&nbsp;Changsha,&nbsp;Wuhan&nbsp;&nbsp;</li>
    <li>private&nbsp;static&nbsp;int[]&nbsp;timeWalk&nbsp;=&nbsp;{&nbsp;5,&nbsp;8,&nbsp;15,&nbsp;15,&nbsp;10&nbsp;};&nbsp;&nbsp;</li>
    <li>//&nbsp;自驾游&nbsp;&nbsp;</li>
    <li>private&nbsp;static&nbsp;int[]&nbsp;timeSelf&nbsp;=&nbsp;{&nbsp;1,&nbsp;3,&nbsp;4,&nbsp;4,&nbsp;5&nbsp;};&nbsp;&nbsp;</li>
    <li>//&nbsp;旅游大巴&nbsp;&nbsp;</li>
    <li>private&nbsp;static&nbsp;int[]&nbsp;timeBus&nbsp;=&nbsp;{&nbsp;2,&nbsp;4,&nbsp;6,&nbsp;6,&nbsp;7&nbsp;};&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>static&nbsp;String&nbsp;now()&nbsp;{&nbsp;&nbsp;</li>
    <li>SimpleDateFormat&nbsp;sdf&nbsp;=&nbsp;new&nbsp;SimpleDateFormat(&#8220;HH:mm:ss&#8221;);&nbsp;&nbsp;</li>
    <li>return&nbsp;sdf.format(new&nbsp;Date())&nbsp;+&nbsp;&#8220;:&nbsp;&#8220;;&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>static&nbsp;class&nbsp;Tour&nbsp;implements&nbsp;Runnable&nbsp;{&nbsp;&nbsp;</li>
    <li>private&nbsp;int[]&nbsp;times;&nbsp;&nbsp;</li>
    <li>private&nbsp;CyclicBarrier&nbsp;barrier;&nbsp;&nbsp;</li>
    <li>private&nbsp;String&nbsp;tourName;&nbsp;&nbsp;</li>
    <li>public&nbsp;Tour(CyclicBarrier&nbsp;barrier,&nbsp;String&nbsp;tourName,&nbsp;int[]&nbsp;times)&nbsp;{&nbsp;&nbsp;</li>
    <li>this.times&nbsp;=&nbsp;times;&nbsp;&nbsp;</li>
    <li>this.tourName&nbsp;=&nbsp;tourName;&nbsp;&nbsp;</li>
    <li>this.barrier&nbsp;=&nbsp;barrier;&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>public&nbsp;void&nbsp;run()&nbsp;{&nbsp;&nbsp;</li>
    <li>try&nbsp;{&nbsp;&nbsp;</li>
    <li>Thread.sleep(times[0]&nbsp;*&nbsp;1000);&nbsp;&nbsp;</li>
    <li>System.out.println(now()&nbsp;+&nbsp;tourName&nbsp;+&nbsp;&#8221;&nbsp;Reached&nbsp;Shenzhen&#8221;);&nbsp;&nbsp;</li>
    <li>barrier.await();&nbsp;&nbsp;</li>
    <li>Thread.sleep(times[1]&nbsp;*&nbsp;1000);&nbsp;&nbsp;</li>
    <li>System.out.println(now()&nbsp;+&nbsp;tourName&nbsp;+&nbsp;&#8221;&nbsp;Reached&nbsp;Guangzhou&#8221;);&nbsp;&nbsp;</li>
    <li>barrier.await();&nbsp;&nbsp;</li>
    <li>Thread.sleep(times[2]&nbsp;*&nbsp;1000);&nbsp;&nbsp;</li>
    <li>System.out.println(now()&nbsp;+&nbsp;tourName&nbsp;+&nbsp;&#8221;&nbsp;Reached&nbsp;Shaoguan&#8221;);&nbsp;&nbsp;</li>
    <li>barrier.await();&nbsp;&nbsp;</li>
    <li>Thread.sleep(times[3]&nbsp;*&nbsp;1000);&nbsp;&nbsp;</li>
    <li>System.out.println(now()&nbsp;+&nbsp;tourName&nbsp;+&nbsp;&#8221;&nbsp;Reached&nbsp;Changsha&#8221;);&nbsp;&nbsp;</li>
    <li>barrier.await();&nbsp;&nbsp;</li>
    <li>Thread.sleep(times[4]&nbsp;*&nbsp;1000);&nbsp;&nbsp;</li>
    <li>System.out.println(now()&nbsp;+&nbsp;tourName&nbsp;+&nbsp;&#8221;&nbsp;Reached&nbsp;Wuhan&#8221;);&nbsp;&nbsp;</li>
    <li>barrier.await();&nbsp;&nbsp;</li>
    <li>}&nbsp;catch&nbsp;(InterruptedException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>}&nbsp;catch&nbsp;(BrokenBarrierException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</li>
    <li>//&nbsp;三个旅行团&nbsp;&nbsp;</li>
    <li>CyclicBarrier&nbsp;barrier&nbsp;=&nbsp;new&nbsp;CyclicBarrier(3);&nbsp;&nbsp;</li>
    <li>ExecutorService&nbsp;exec&nbsp;=&nbsp;Executors.newFixedThreadPool(3);&nbsp;&nbsp;</li>
    <li>exec.submit(new&nbsp;Tour(barrier,&nbsp;&#8220;WalkTour&#8221;,&nbsp;timeWalk));&nbsp;&nbsp;</li>
    <li>exec.submit(new&nbsp;Tour(barrier,&nbsp;&#8220;SelfTour&#8221;,&nbsp;timeSelf));&nbsp;&nbsp;</li>
    <li>exec.submit(new&nbsp;Tour(barrier,&nbsp;&#8220;BusTour&#8221;,&nbsp;timeBus));&nbsp;&nbsp;</li>
    <li>exec.shutdown();&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package concurrent;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestCyclicBarrier {
// 徒步需要的时间: Shenzhen, Guangzhou, Shaoguan, Changsha, Wuhan
private static int[] timeWalk = { 5, 8, 15, 15, 10 };
// 自驾游
private static int[] timeSelf = { 1, 3, 4, 4, 5 };
// 旅游大巴
private static int[] timeBus = { 2, 4, 6, 6, 7 };
static String now() {
SimpleDateFormat sdf = new SimpleDateFormat(&#8220;HH:mm:ss&#8221;);
return sdf.format(new Date()) + &#8220;: &#8220;;
}
static class Tour implements Runnable {
private int[] times;
private CyclicBarrier barrier;
private String tourName;
public Tour(CyclicBarrier barrier, String tourName, int[] times) {
this.times = times;
this.tourName = tourName;
this.barrier = barrier;
}
public void run() {
try {
Thread.sleep(times[0] * 1000);
System.out.println(now() + tourName + &#8221; Reached Shenzhen&#8221;);
barrier.await();
Thread.sleep(times[1] * 1000);
System.out.println(now() + tourName + &#8221; Reached Guangzhou&#8221;);
barrier.await();
Thread.sleep(times[2] * 1000);
System.out.println(now() + tourName + &#8221; Reached Shaoguan&#8221;);
barrier.await();
Thread.sleep(times[3] * 1000);
System.out.println(now() + tourName + &#8221; Reached Changsha&#8221;);
barrier.await();
Thread.sleep(times[4] * 1000);
System.out.println(now() + tourName + &#8221; Reached Wuhan&#8221;);
barrier.await();
} catch (InterruptedException e) {
} catch (BrokenBarrierException e) {
}
}
}
public static void main(String[] args) {
// 三个旅行团
CyclicBarrier barrier = new CyclicBarrier(3);
ExecutorService exec = Executors.newFixedThreadPool(3);
exec.submit(new Tour(barrier, &#8220;WalkTour&#8221;, timeWalk));
exec.submit(new Tour(barrier, &#8220;SelfTour&#8221;, timeSelf));
exec.submit(new Tour(barrier, &#8220;BusTour&#8221;, timeBus));
exec.shutdown();
}
}
</pre>
<br />
运行结果：
<br />
00:02:25: SelfTour Reached Shenzhen
<br />
00:02:25: BusTour Reached Shenzhen
<br />
00:02:27: WalkTour Reached Shenzhen
<br />
00:02:30: SelfTour Reached Guangzhou
<br />
00:02:31: BusTour Reached Guangzhou
<br />
00:02:35: WalkTour Reached Guangzhou
<br />
00:02:39: SelfTour Reached Shaoguan
<br />
00:02:41: BusTour Reached Shaoguan
<br />
<br />
并发库中的BlockingQueue是一个比较好玩的类，顾名思义，就是阻塞队列。该类主要提供了两个方法put()和take()，前者将一
个对象放到队列中，如果队列已经满了，就等待直到有空闲节点；后者从head取一个对象，如果没有对象，就等待直到有可取的对象。
<br />
<br />
下面的例子比较简单，一个读线程，用于将要处理的文件对象添加到阻塞队列中，另外四个写线程用于取出文件对象，为了模拟写操作耗时长的特点，特让
线程睡眠一段随机长度的时间。另外，该Demo也使用到了线程池和原子整型（AtomicInteger），AtomicInteger可以在并发情况下
达到原子化更新，避免使用了synchronized，而且性能非常高。由于阻塞队列的put和take操作会阻塞，为了使线程退出，特在队列中添加了一
个&#8220;标识&#8221;，算法中也叫&#8220;哨兵&#8221;，当发现这个哨兵后，写线程就退出。
<br />
<br />
当然线程池也要显式退出了。
<br />
<br />
<div>
<div>
<div>Java代码 <a href="http://daoger.javaeye.com/blog/142485#" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" title="复制代码"><img src="http://daoger.javaeye.com/images/icon_copy.gif" alt="复制代码" /></a></div>
</div>
<ol start="1">
    <li>package&nbsp;concurrent;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.io.File;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.io.FileFilter;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.BlockingQueue;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutorService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.LinkedBlockingQueue;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.atomic.AtomicInteger;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TestBlockingQueue&nbsp;{&nbsp;&nbsp;</li>
    <li>static&nbsp;long&nbsp;randomTime()&nbsp;{&nbsp;&nbsp;</li>
    <li>return&nbsp;(long)&nbsp;(Math.random()&nbsp;*&nbsp;1000);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</li>
    <li>//&nbsp;能容纳100个文件&nbsp;&nbsp;</li>
    <li>final&nbsp;BlockingQueue&nbsp;queue&nbsp;=&nbsp;new&nbsp;LinkedBlockingQueue(100);&nbsp;&nbsp;</li>
    <li>//&nbsp;线程池&nbsp;&nbsp;</li>
    <li>final&nbsp;ExecutorService&nbsp;exec&nbsp;=&nbsp;Executors.newFixedThreadPool(5);&nbsp;&nbsp;</li>
    <li>final&nbsp;File&nbsp;root&nbsp;=&nbsp;new&nbsp;File(&#8220;F:""JavaLib&#8221;);&nbsp;&nbsp;</li>
    <li>//&nbsp;完成标志&nbsp;&nbsp;</li>
    <li>final&nbsp;File&nbsp;exitFile&nbsp;=&nbsp;new&nbsp;File(&#8220;&#8221;);&nbsp;&nbsp;</li>
    <li>//&nbsp;读个数&nbsp;&nbsp;</li>
    <li>final&nbsp;AtomicInteger&nbsp;rc&nbsp;=&nbsp;new&nbsp;AtomicInteger();&nbsp;&nbsp;</li>
    <li>//&nbsp;写个数&nbsp;&nbsp;</li>
    <li>final&nbsp;AtomicInteger&nbsp;wc&nbsp;=&nbsp;new&nbsp;AtomicInteger();&nbsp;&nbsp;</li>
    <li>//&nbsp;读线程&nbsp;&nbsp;</li>
    <li>Runnable&nbsp;read&nbsp;=&nbsp;new&nbsp;Runnable()&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;void&nbsp;run()&nbsp;{&nbsp;&nbsp;</li>
    <li>scanFile(root);&nbsp;&nbsp;</li>
    <li>scanFile(exitFile);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;void&nbsp;scanFile(File&nbsp;file)&nbsp;{&nbsp;&nbsp;</li>
    <li>if&nbsp;(file.isDirectory())&nbsp;{&nbsp;&nbsp;</li>
    <li>File[]&nbsp;files&nbsp;=&nbsp;file.listFiles(new&nbsp;FileFilter()&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;boolean&nbsp;accept(File&nbsp;pathname)&nbsp;{&nbsp;&nbsp;</li>
    <li>return&nbsp;pathname.isDirectory()&nbsp;&nbsp;</li>
    <li>||&nbsp;pathname.getPath().endsWith(&#8220;.java&#8221;);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>});&nbsp;&nbsp;</li>
    <li>for&nbsp;(File&nbsp;one&nbsp;:&nbsp;files)&nbsp;&nbsp;</li>
    <li>scanFile(one);&nbsp;&nbsp;</li>
    <li>}&nbsp;else&nbsp;{&nbsp;&nbsp;</li>
    <li>try&nbsp;{&nbsp;&nbsp;</li>
    <li>int&nbsp;index&nbsp;=&nbsp;rc.incrementAndGet();&nbsp;&nbsp;</li>
    <li>System.out.println(&#8220;Read0:&nbsp;&#8221;&nbsp;+&nbsp;index&nbsp;+&nbsp;&#8221;&nbsp;&#8220;&nbsp;&nbsp;</li>
    <li>+&nbsp;file.getPath());&nbsp;&nbsp;</li>
    <li>queue.put(file);&nbsp;&nbsp;</li>
    <li>}&nbsp;catch&nbsp;(InterruptedException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>};&nbsp;&nbsp;</li>
    <li>exec.submit(read);&nbsp;&nbsp;</li>
    <li>//&nbsp;四个写线程&nbsp;&nbsp;</li>
    <li>for&nbsp;(int&nbsp;index&nbsp;=&nbsp;0;&nbsp;index&nbsp;&lt;&nbsp;4;&nbsp;index++)&nbsp;{&nbsp;&nbsp;</li>
    <li>//&nbsp;write&nbsp;thread&nbsp;&nbsp;</li>
    <li>final&nbsp;int&nbsp;NO&nbsp;=&nbsp;index;&nbsp;&nbsp;</li>
    <li>Runnable&nbsp;write&nbsp;=&nbsp;new&nbsp;Runnable()&nbsp;{&nbsp;&nbsp;</li>
    <li>String&nbsp;threadName&nbsp;=&nbsp;&#8220;Write&#8221;&nbsp;+&nbsp;NO;&nbsp;&nbsp;</li>
    <li>public&nbsp;void&nbsp;run()&nbsp;{&nbsp;&nbsp;</li>
    <li>while&nbsp;(true)&nbsp;{&nbsp;&nbsp;</li>
    <li>try&nbsp;{&nbsp;&nbsp;</li>
    <li>Thread.sleep(randomTime());&nbsp;&nbsp;</li>
    <li>int&nbsp;index&nbsp;=&nbsp;wc.incrementAndGet();&nbsp;&nbsp;</li>
    <li>File&nbsp;file&nbsp;=&nbsp;queue.take();&nbsp;&nbsp;</li>
    <li>//&nbsp;队列已经无对象&nbsp;&nbsp;</li>
    <li>if&nbsp;(file&nbsp;==&nbsp;exitFile)&nbsp;{&nbsp;&nbsp;</li>
    <li>//&nbsp;再次添加&#8221;标志&#8221;，以让其他线程正常退出&nbsp;&nbsp;</li>
    <li>queue.put(exitFile);&nbsp;&nbsp;</li>
    <li>break;&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>System.out.println(threadName&nbsp;+&nbsp;&#8220;:&nbsp;&#8221;&nbsp;+&nbsp;index&nbsp;+&nbsp;&#8221;&nbsp;&#8220;&nbsp;&nbsp;</li>
    <li>+&nbsp;file.getPath());&nbsp;&nbsp;</li>
    <li>}&nbsp;catch&nbsp;(InterruptedException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>};&nbsp;&nbsp;</li>
    <li>exec.submit(write);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>exec.shutdown();&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package concurrent;
import java.io.File;
import java.io.FileFilter;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class TestBlockingQueue {
static long randomTime() {
return (long) (Math.random() * 1000);
}
public static void main(String[] args) {
// 能容纳100个文件
final BlockingQueue queue = new LinkedBlockingQueue(100);
// 线程池
final ExecutorService exec = Executors.newFixedThreadPool(5);
final File root = new File(&#8220;F:""JavaLib&#8221;);
// 完成标志
final File exitFile = new File(&#8220;&#8221;);
// 读个数
final AtomicInteger rc = new AtomicInteger();
// 写个数
final AtomicInteger wc = new AtomicInteger();
// 读线程
Runnable read = new Runnable() {
public void run() {
scanFile(root);
scanFile(exitFile);
}
public void scanFile(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.isDirectory()
|| pathname.getPath().endsWith(&#8220;.java&#8221;);
}
});
for (File one : files)
scanFile(one);
} else {
try {
int index = rc.incrementAndGet();
System.out.println(&#8220;Read0: &#8221; + index + &#8221; &#8220;
+ file.getPath());
queue.put(file);
} catch (InterruptedException e) {
}
}
}
};
exec.submit(read);
// 四个写线程
for (int index = 0; index &lt; 4; index++) {
// write thread
final int NO = index;
Runnable write = new Runnable() {
String threadName = &#8220;Write&#8221; + NO;
public void run() {
while (true) {
try {
Thread.sleep(randomTime());
int index = wc.incrementAndGet();
File file = queue.take();
// 队列已经无对象
if (file == exitFile) {
// 再次添加&#8221;标志&#8221;，以让其他线程正常退出
queue.put(exitFile);
break;
}
System.out.println(threadName + &#8220;: &#8221; + index + &#8221; &#8220;
+ file.getPath());
} catch (InterruptedException e) {
}
}
}
};
exec.submit(write);
}
exec.shutdown();
}
}
</pre>
<br />
从名字可以看出，CountDownLatch是一个倒数计数的锁，当倒数到0时触发事件，也就是开锁，其他人就可以进入了。在一些应用场合中，需要等待某个条件达到要求后才能做后面的事情；同时当线程都完成后也会触发事件，以便进行后面的操作。
<br />
<br />
<br />
CountDownLatch最重要的方法是countDown()和await()，前者主要是倒数一次，后者是等待倒数到0，如果没有到达0，就只有阻塞等待了。
<br />
<br />
一个CountDouwnLatch实例是不能重复使用的，也就是说它是一次性的，锁一经被打开就不能再关闭使用了，如果想重复使用，请考虑使用CyclicBarrier。
<br />
<br />
下面的例子简单的说明了CountDownLatch的使用方法，模拟了100米赛跑，10名选手已经准备就绪，只等裁判一声令下。当所有人都到达终点时，比赛结束。
<br />
<br />
同样，线程池需要显式shutdown。
<br />
<div>
<div>
<div>Java代码 <a href="http://daoger.javaeye.com/blog/142485#" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" title="复制代码"><img src="http://daoger.javaeye.com/images/icon_copy.gif" alt="复制代码" /></a></div>
</div>
<ol start="1">
    <li>package&nbsp;concurrent;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.CountDownLatch;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutorService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TestCountDownLatch&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;InterruptedException&nbsp;{&nbsp;&nbsp;</li>
    <li>//&nbsp;开始的倒数锁&nbsp;&nbsp;</li>
    <li>final&nbsp;CountDownLatch&nbsp;begin&nbsp;=&nbsp;new&nbsp;CountDownLatch(1);&nbsp;&nbsp;</li>
    <li>//&nbsp;结束的倒数锁&nbsp;&nbsp;</li>
    <li>final&nbsp;CountDownLatch&nbsp;end&nbsp;=&nbsp;new&nbsp;CountDownLatch(10);&nbsp;&nbsp;</li>
    <li>//&nbsp;十名选手&nbsp;&nbsp;</li>
    <li>final&nbsp;ExecutorService&nbsp;exec&nbsp;=&nbsp;Executors.newFixedThreadPool(10);&nbsp;&nbsp;</li>
    <li>for(int&nbsp;index&nbsp;=&nbsp;0;&nbsp;index&nbsp;&lt;&nbsp;10;&nbsp;index++)&nbsp;{&nbsp;&nbsp;</li>
    <li>final&nbsp;int&nbsp;NO&nbsp;=&nbsp;index&nbsp;+&nbsp;1;&nbsp;&nbsp;</li>
    <li>Runnable&nbsp;run&nbsp;=&nbsp;new&nbsp;Runnable(){&nbsp;&nbsp;</li>
    <li>public&nbsp;void&nbsp;run()&nbsp;{&nbsp;&nbsp;</li>
    <li>try&nbsp;{&nbsp;&nbsp;</li>
    <li>begin.await();&nbsp;&nbsp;</li>
    <li>Thread.sleep((long)&nbsp;(Math.random()&nbsp;*&nbsp;10000));&nbsp;&nbsp;</li>
    <li>System.out.println(&#8220;No.&#8221;&nbsp;+&nbsp;NO&nbsp;+&nbsp;&#8221;&nbsp;arrived&#8221;);&nbsp;&nbsp;</li>
    <li>}&nbsp;catch&nbsp;(InterruptedException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>}&nbsp;finally&nbsp;{&nbsp;&nbsp;</li>
    <li>end.countDown();&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>};&nbsp;&nbsp;</li>
    <li>exec.submit(run);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>System.out.println(&#8220;Game&nbsp;Start&#8221;);&nbsp;&nbsp;</li>
    <li>begin.countDown();&nbsp;&nbsp;</li>
    <li>end.await();&nbsp;&nbsp;</li>
    <li>System.out.println(&#8220;Game&nbsp;Over&#8221;);&nbsp;&nbsp;</li>
    <li>exec.shutdown();&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package concurrent;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestCountDownLatch {
public static void main(String[] args) throws InterruptedException {
// 开始的倒数锁
final CountDownLatch begin = new CountDownLatch(1);
// 结束的倒数锁
final CountDownLatch end = new CountDownLatch(10);
// 十名选手
final ExecutorService exec = Executors.newFixedThreadPool(10);
for(int index = 0; index &lt; 10; index++) {
final int NO = index + 1;
Runnable run = new Runnable(){
public void run() {
try {
begin.await();
Thread.sleep((long) (Math.random() * 10000));
System.out.println(&#8220;No.&#8221; + NO + &#8221; arrived&#8221;);
} catch (InterruptedException e) {
} finally {
end.countDown();
}
}
};
exec.submit(run);
}
System.out.println(&#8220;Game Start&#8221;);
begin.countDown();
end.await();
System.out.println(&#8220;Game Over&#8221;);
exec.shutdown();
}
}
</pre>
<br />
运行结果:
<br />
Game Start
<br />
No.4 arrived
<br />
No.1 arrived
<br />
No.7 arrived
<br />
No.9 arrived
<br />
No.3 arrived
<br />
No.2 arrived
<br />
No.8 arrived
<br />
No.10 arrived
<br />
No.6 arrived
<br />
No.5 arrived
<br />
Game Over
<br />
<br />
有时候在实际应用中，某些操作很耗时，但又不是不可或缺的步骤。比如用网页浏览器浏览新闻时，最重要的是要显示文字内容，至于与新闻相匹配的图片
就没有那么重要的，所以此时首先保证文字信息先显示，而图片信息会后显示，但又不能不显示，由于下载图片是一个耗时的操作，所以必须一开始就得下载。
<br />
<br />
<br />
Java的并发库的Future类就可以满足这个要求。Future的重要方法包括get()和cancel()，get()获取数据对象，如果
数据没有加载，就会阻塞直到取到数据，而
cancel()是取消数据加载。另外一个get(timeout)操作，表示如果在timeout时间内没有取到就失败返回，而不再阻塞。
<br />
<br />
下面的Demo简单的说明了Future的使用方法：一个非常耗时的操作必须一开始启动，但又不能一直等待；其他重要的事情又必须做，等完成后，就可以做不重要的事情。
<br />
<div>
<div>
<div>Java代码 <a href="http://daoger.javaeye.com/blog/142485#" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" title="复制代码"><img src="http://daoger.javaeye.com/images/icon_copy.gif" alt="复制代码" /></a></div>
</div>
<ol start="1">
    <li>package&nbsp;concurrent;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Callable;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutionException;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutorService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Future;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TestFutureTask&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)throws&nbsp;InterruptedException,&nbsp;&nbsp;</li>
    <li>ExecutionException&nbsp;{&nbsp;&nbsp;</li>
    <li>final&nbsp;ExecutorService&nbsp;exec&nbsp;=&nbsp;Executors.newFixedThreadPool(5);&nbsp;&nbsp;</li>
    <li>Callable&nbsp;call&nbsp;=&nbsp;new&nbsp;Callable()&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;String&nbsp;call()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li>
    <li>Thread.sleep(1000&nbsp;*&nbsp;5);&nbsp;&nbsp;</li>
    <li>return&nbsp;&#8220;Other&nbsp;less&nbsp;important&nbsp;but&nbsp;longtime&nbsp;things.&#8221;;&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>};&nbsp;&nbsp;</li>
    <li>Future&nbsp;task&nbsp;=&nbsp;exec.submit(call);&nbsp;&nbsp;</li>
    <li>//&nbsp;重要的事情&nbsp;&nbsp;</li>
    <li>Thread.sleep(1000&nbsp;*&nbsp;3);&nbsp;&nbsp;</li>
    <li>System.out.println(&#8220;Let&#8217;s&nbsp;do&nbsp;important&nbsp;things.&#8221;);&nbsp;&nbsp;</li>
    <li>//&nbsp;其他不重要的事情&nbsp;&nbsp;</li>
    <li>String&nbsp;obj&nbsp;=&nbsp;task.get();&nbsp;&nbsp;</li>
    <li>System.out.println(obj);&nbsp;&nbsp;</li>
    <li>//&nbsp;关闭线程池&nbsp;&nbsp;</li>
    <li>exec.shutdown();&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestFutureTask {
public static void main(String[] args)throws InterruptedException,
ExecutionException {
final ExecutorService exec = Executors.newFixedThreadPool(5);
Callable call = new Callable() {
public String call() throws Exception {
Thread.sleep(1000 * 5);
return &#8220;Other less important but longtime things.&#8221;;
}
};
Future task = exec.submit(call);
// 重要的事情
Thread.sleep(1000 * 3);
System.out.println(&#8220;Let&#8217;s do important things.&#8221;);
// 其他不重要的事情
String obj = task.get();
System.out.println(obj);
// 关闭线程池
exec.shutdown();
}
}
</pre>
<br />
运行结果：
<br />
Let&#8217;s do important things.
<br />
Other less important but longtime things.
<br />
<br />
考虑以下场景：浏览网页时，浏览器了5个线程下载网页中的图片文件，由于图片大小、网站访问速度等诸多因素的影响，完成图片下载的时间就会有很大的不同。如果先下载完成的图片就会被先显示到界面上，反之，后下载的图片就后显示。
<br />
<br />
<br />
Java的并发库的CompletionService可以满足这种场景要求。该接口有两个重要方法：submit()和take()。
submit用于提交一个runnable或者callable，一般会提交给一个线程池处理；而take就是取出已经执行完毕runnable或者
callable实例的Future对象，如果没有满足要求的，就等待了。
CompletionService还有一个对应的方法poll，该方法与take类似，只是不会等待，如果没有满足要求，就返回null对象。
<br />
<div>
<div>
<div>Java代码 <a href="http://daoger.javaeye.com/blog/142485#" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" title="复制代码"><img src="http://daoger.javaeye.com/images/icon_copy.gif" alt="复制代码" /></a></div>
</div>
<ol start="1">
    <li>package&nbsp;concurrent;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Callable;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.CompletionService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutionException;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutorCompletionService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutorService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Future;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TestCompletionService&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;InterruptedException,&nbsp;&nbsp;</li>
    <li>ExecutionException&nbsp;{&nbsp;&nbsp;</li>
    <li>ExecutorService&nbsp;exec&nbsp;=&nbsp;Executors.newFixedThreadPool(10);&nbsp;&nbsp;</li>
    <li>CompletionService&nbsp;serv&nbsp;=&nbsp;&nbsp;</li>
    <li>new&nbsp;ExecutorCompletionService(exec);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>for&nbsp;(int&nbsp;index&nbsp;=&nbsp;0;&nbsp;index&nbsp;&lt;&nbsp;5;&nbsp;index++)&nbsp;{&nbsp;&nbsp;</li>
    <li>final&nbsp;int&nbsp;NO&nbsp;=&nbsp;index;&nbsp;&nbsp;</li>
    <li>Callable&nbsp;downImg&nbsp;=&nbsp;new&nbsp;Callable()&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;String&nbsp;call()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;</li>
    <li>Thread.sleep((long)&nbsp;(Math.random()&nbsp;*&nbsp;10000));&nbsp;&nbsp;</li>
    <li>return&nbsp;&#8220;Downloaded&nbsp;Image&nbsp;&#8221;&nbsp;+&nbsp;NO;&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>};&nbsp;&nbsp;</li>
    <li>serv.submit(downImg);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>Thread.sleep(1000&nbsp;*&nbsp;2);&nbsp;&nbsp;</li>
    <li>System.out.println(&#8220;Show&nbsp;web&nbsp;content&#8221;);&nbsp;&nbsp;</li>
    <li>for&nbsp;(int&nbsp;index&nbsp;=&nbsp;0;&nbsp;index&nbsp;&lt;&nbsp;5;&nbsp;index++)&nbsp;{&nbsp;&nbsp;</li>
    <li>Future&nbsp;task&nbsp;=&nbsp;serv.take();&nbsp;&nbsp;</li>
    <li>String&nbsp;img&nbsp;=&nbsp;task.get();&nbsp;&nbsp;</li>
    <li>System.out.println(img);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>System.out.println(&#8220;End&#8221;);&nbsp;&nbsp;</li>
    <li>//&nbsp;关闭线程池&nbsp;&nbsp;</li>
    <li>exec.shutdown();&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestCompletionService {
public static void main(String[] args) throws InterruptedException,
ExecutionException {
ExecutorService exec = Executors.newFixedThreadPool(10);
CompletionService serv =
new ExecutorCompletionService(exec);
for (int index = 0; index &lt; 5; index++) {
final int NO = index;
Callable downImg = new Callable() {
public String call() throws Exception {
Thread.sleep((long) (Math.random() * 10000));
return &#8220;Downloaded Image &#8221; + NO;
}
};
serv.submit(downImg);
}
Thread.sleep(1000 * 2);
System.out.println(&#8220;Show web content&#8221;);
for (int index = 0; index &lt; 5; index++) {
Future task = serv.take();
String img = task.get();
System.out.println(img);
}
System.out.println(&#8220;End&#8221;);
// 关闭线程池
exec.shutdown();
}
}
</pre>
<br />
运行结果:
<br />
Show web content
<br />
Downloaded Image 1
<br />
Downloaded Image 2
<br />
Downloaded Image 4
<br />
Downloaded Image 0
<br />
Downloaded Image 3
<br />
End
<br />
<br />
操作系统的信号量是个很重要的概念，在进程控制方面都有应用。Java并发库的Semaphore可以很轻松完成信号量控制，Semaphore
可以控制某个资源可被同时访问的个数，acquire()获取一个许可，如果没有就等待，而release()释放一个许可。比如在Windows下可以
设置共享文件的最大客户端访问个数。
<br />
<br />
Semaphore维护了当前访问的个数，提供同步机制，控制同时访问的个数。在数据结构中链表可以保存&#8220;无限&#8221;的节点，用Semaphore可以实现有限大小的链表。另外重入锁ReentrantLock也可以实现该功能，但实现上要负责些，代码也要复杂些。
<br />
<br />
下面的Demo中申明了一个只有5个许可的Semaphore，而有20个线程要访问这个资源，通过acquire()和release()获取和释放访问许可。
<br />
<div>
<div>
<div>Java代码 <a href="http://daoger.javaeye.com/blog/142485#" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" title="复制代码"><img src="http://daoger.javaeye.com/images/icon_copy.gif" alt="复制代码" /></a></div>
</div>
<ol start="1">
    <li>package&nbsp;concurrent;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.ExecutorService;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Executors;&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.concurrent.Semaphore;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;TestSemaphore&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</li>
    <li>//&nbsp;线程池&nbsp;&nbsp;</li>
    <li>ExecutorService&nbsp;exec&nbsp;=&nbsp;Executors.newCachedThreadPool();&nbsp;&nbsp;</li>
    <li>//&nbsp;只能5个线程同时访问&nbsp;&nbsp;</li>
    <li>final&nbsp;Semaphore&nbsp;semp&nbsp;=&nbsp;new&nbsp;Semaphore(5);&nbsp;&nbsp;</li>
    <li>//&nbsp;模拟20个客户端访问&nbsp;&nbsp;</li>
    <li>for&nbsp;(int&nbsp;index&nbsp;=&nbsp;0;&nbsp;index&nbsp;&lt;&nbsp;20;&nbsp;index++)&nbsp;{&nbsp;&nbsp;</li>
    <li>final&nbsp;int&nbsp;NO&nbsp;=&nbsp;index;&nbsp;&nbsp;</li>
    <li>Runnable&nbsp;run&nbsp;=&nbsp;new&nbsp;Runnable()&nbsp;{&nbsp;&nbsp;</li>
    <li>public&nbsp;void&nbsp;run()&nbsp;{&nbsp;&nbsp;</li>
    <li>try&nbsp;{&nbsp;&nbsp;</li>
    <li>//&nbsp;获取许可&nbsp;&nbsp;</li>
    <li>semp.acquire();&nbsp;&nbsp;</li>
    <li>System.out.println(&#8220;Accessing:&nbsp;&#8221;&nbsp;+&nbsp;NO);&nbsp;&nbsp;</li>
    <li>Thread.sleep((long)&nbsp;(Math.random()&nbsp;*&nbsp;10000));&nbsp;&nbsp;</li>
    <li>//&nbsp;访问完后，释放&nbsp;&nbsp;</li>
    <li>semp.release();&nbsp;&nbsp;</li>
    <li>}&nbsp;catch&nbsp;(InterruptedException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>};&nbsp;&nbsp;</li>
    <li>exec.execute(run);&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>//&nbsp;退出线程池&nbsp;&nbsp;</li>
    <li>exec.shutdown();&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">package concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class TestSemaphore {
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只能5个线程同时访问
final Semaphore semp = new Semaphore(5);
// 模拟20个客户端访问
for (int index = 0; index &lt; 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可
semp.acquire();
System.out.println(&#8220;Accessing: &#8221; + NO);
Thread.sleep((long) (Math.random() * 10000));
// 访问完后，释放
semp.release();
} catch (InterruptedException e) {
}
}
};
exec.execute(run);
}
// 退出线程池
exec.shutdown();
}
}
</pre>
<br />
运行结果：
<br />
Accessing: 0
<br />
Accessing: 1
<br />
Accessing: 2
<br />
Accessing: 3
<br />
Accessing: 4
<br />
Accessing: 5
<br />
Accessing: 6
<br />
Accessing: 7
<br />
Accessing: 8
<br />
Accessing: 9
<br />
Accessing: 10
<br />
Accessing: 11
<br />
Accessing: 12
<br />
Accessing: 13
<br />
Accessing: 14
<br />
Accessing: 15
<br />
Accessing: 16
<br />
Accessing: 17
<br />
Accessing: 18
<br />
Accessing: 19
<img src ="http://www.blogjava.net/java-blog/aggbug/193845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-04-17 19:11 <a href="http://www.blogjava.net/java-blog/articles/193845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Sun HotSpot 1.4.1 JVM堆大小的调整</title><link>http://www.blogjava.net/java-blog/articles/193455.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Wed, 16 Apr 2008 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/193455.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/193455.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/193455.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/193455.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/193455.html</trackback:ping><description><![CDATA[<div>
<a id="viewpost1_TitleUrl" class="postTitle2" href="../../jspark/archive/2006/11/28/84008.html"><br />
</a>
</div>
<strong>Sun HotSpot 1.4.1 JVM堆大小的调整<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;Sun
HotSpot
1.4.1使用分代收集器，它把堆分为三个主要的域：新域、旧域以及永久域。Jvm生成的所有新对象放在新域中。一旦对象经历了一定数量的垃圾收集循环
后，便获得使用期并进入旧域。在永久域中jvm则存储class和method对象。就配置而言，永久域是一个独立域并且不认为是堆的一部分。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;下面介绍如何控制这些域的大小。可使用-Xms和-Xmx 控制整个堆的原始大小或最大值。<br />
&nbsp;&nbsp;&nbsp;&nbsp;下面的命令是把初始大小设置为128M：<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">java &#8211;Xms128m</span><br />
&nbsp;&nbsp;&nbsp;&nbsp; &#8211;Xmx256m为控制新域的大小，可使用-XX:NewRatio设置新域在堆中所占的比例。<br />
<br />
&nbsp;&nbsp; 下面的命令把整个堆设置成128m，新域比率设置成3，即新域与旧域比例为1：3，新域为堆的1/4或32M：<br />
&nbsp;&nbsp; <span style="color: blue;">java &#8211;Xms128m &#8211;Xmx128m</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&#8211;XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize设置新域的初始值和最大值。<br />
<br />
&nbsp;&nbsp; 下面的命令把新域的初始值和最大值设置成64m: <br />
&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue;">java &#8211;Xms256m &#8211;Xmx256m &#8211;Xmn64m</span><br />
&nbsp;&nbsp; 永久域默认大小为4m。运行程序时，jvm会调整永久域的大小以满足需要。每次调整时，jvm会对堆进行一次完全的垃圾收集。<br />
<br />
&nbsp;&nbsp;
使用-XX:MaxPerSize标志来增加永久域搭大小。在WebLogic
Server应用程序加载较多类时，经常需要增加永久域的最大值。当jvm加载类时，永久域中的对象急剧增加，从而使jvm不断调整永久域大小。为了避免
调整，可使用-XX:PerSize标志设置初始值。<br />
&nbsp;&nbsp; 下面把永久域初始值设置成32m，最大值设置成64m。<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m</span><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;
默认状态下，HotSpot在新域中使用复制收集器。该域一般分为三个部分。第一部分为Eden，用于生成新的对象。另两部分称为救助空间，当Eden充
满时，收集器停止应用程序，把所有可到达对象复制到当前的from救助空间，一旦当前的from救助空间充满，收集器则把可到达对象复制到当前的to救助
空间。From和to救助空间互换角色。维持活动的对象将在救助空间不断复制，直到它们获得使用期并转入旧域。使用-XX:SurvivorRatio可
控制新域子空间的大小。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;同NewRation一样，SurvivorRation规定某救助域与Eden空间的比值。比如，以下命令把新域设置成64m，Eden占32m，每个救助域各占16m：<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2</span><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;
如前所述，默认状态下HotSpot对新域使用复制收集器，对旧域使用标记－清除－压缩收集器。在新域中使用复制收集器有很多意义，因为应用程序生成的大
部分对象是短寿命的。理想状态下，所有过渡对象在移出Eden空间时将被收集。如果能够这样的话，并且移出Eden空间的对象是长寿命的，那么理论上可以
立即把它们移进旧域，避免在救助空间反复复制。但是，应用程序不能适合这种理想状态，因为它们有一小部分中长寿命的对象。最好是保持这些中长寿命的对象并
放在新域中，因为复制小部分的对象总比压缩旧域廉价。为控制新域中对象的复制，可用-XX:TargetSurvivorRatio控制救助空间的比例
（该值是设置救助空间的使用比例。如救助空间位1M，该值50表示可用500K）。该值是一个百分比，默认值是50。当较大的堆栈使用较低的
sruvivorratio时，应增加该值到80至90，以更好利用救助空间。用-XX:maxtenuring threshold可控制上限。<br />
<br />
&nbsp;&nbsp; 为放置所有的复制全部发生以及希望对象从eden扩展到旧域，可以把MaxTenuring Threshold设置成0。设置完成后，实际上就不再使用救助空间了，因此应把SurvivorRatio设成最大值以最大化Eden空间，设置如下：<br />
&nbsp;&nbsp; <span style="color: blue;">java &#8230; -XX:MaxTenuringThreshold=0 &#8211;XX:SurvivorRatio＝50000 &#8230;</span><br />
<img src ="http://www.blogjava.net/java-blog/aggbug/193455.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-04-16 15:19 <a href="http://www.blogjava.net/java-blog/articles/193455.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个很耗时的运算需要缓存其计算结果，采用备忘录模式实现</title><link>http://www.blogjava.net/java-blog/articles/191992.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Thu, 10 Apr 2008 14:30:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/191992.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/191992.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/191992.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/191992.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/191992.html</trackback:ping><description><![CDATA[有一个很耗时的运算需要缓存其计算结果，采用备忘录模式实现，如：
<br />
<div>
<div>
<div>Java代码&nbsp;</div>
</div>
<ol start="1">
    <li>public&nbsp;interface&nbsp;Computable&lt;A,&nbsp;V&gt;&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;compute(A&nbsp;arg)&nbsp;throws&nbsp;InterruptedException;&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;ExpensiveFunction&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;implements&nbsp;Computable&lt;String,&nbsp;BigInteger&gt;&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;BigInteger&nbsp;compute(String&nbsp;arg)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;假设这里非常耗时...&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;BigInteger(arg);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">public interface Computable&lt;A, V&gt; {
V compute(A arg) throws InterruptedException;
}
public class ExpensiveFunction
implements Computable&lt;String, BigInteger&gt; {
public BigInteger compute(String arg) {
// 假设这里非常耗时...
return new BigInteger(arg);
}
}
</pre>
<br />
<br />
备忘录缓存方案一：
<br />
<div>
<div>
<div>Java代码&nbsp;</div>
</div>
<ol start="1">
    <li>public&nbsp;class&nbsp;Memoizer1&lt;A,&nbsp;V&gt;&nbsp;implements&nbsp;Computable&lt;A,&nbsp;V&gt;&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;@GuardedBy("this")&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;Map&lt;A,&nbsp;V&gt;&nbsp;cache&nbsp;=&nbsp;new&nbsp;HashMap&lt;A,&nbsp;V&gt;();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;Computable&lt;A,&nbsp;V&gt;&nbsp;c;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Memoizer1(Computable&lt;A,&nbsp;V&gt;&nbsp;c)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.c&nbsp;=&nbsp;c;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;synchronized&nbsp;V&nbsp;compute(A&nbsp;arg)&nbsp;throws&nbsp;InterruptedException&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;result&nbsp;=&nbsp;cache.get(arg);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(result&nbsp;==&nbsp;null)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;c.compute(arg);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.put(arg,&nbsp;result);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">public class Memoizer1&lt;A, V&gt; implements Computable&lt;A, V&gt; {
@GuardedBy("this")
private final Map&lt;A, V&gt; cache = new HashMap&lt;A, V&gt;();
private final Computable&lt;A, V&gt; c;
public Memoizer1(Computable&lt;A, V&gt; c) {
this.c = c;
}
public synchronized V compute(A arg) throws InterruptedException {
V result = cache.get(arg);
if (result == null) {
result = c.compute(arg);
cache.put(arg, result);
}
return result;
}
}
</pre>
<br />
这里备忘录的整个compute过程被同步，相当于我最原始的低效方案，
<br />
<br />
<br />
备忘录缓存方案二：
<br />
<div>
<div>
<div>Java代码&nbsp;</div>
</div>
<ol start="1">
    <li>public&nbsp;class&nbsp;Memoizer2&lt;A,&nbsp;V&gt;&nbsp;implements&nbsp;Computable&lt;A,&nbsp;V&gt;&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;Map&lt;A,&nbsp;V&gt;&nbsp;cache&nbsp;=&nbsp;new&nbsp;ConcurrentHashMap&lt;A,&nbsp;V&gt;();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;Computable&lt;A,&nbsp;V&gt;&nbsp;c;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Memoizer2(Computable&lt;A,&nbsp;V&gt;&nbsp;c)&nbsp;{&nbsp;this.c&nbsp;=&nbsp;c;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;V&nbsp;compute(A&nbsp;arg)&nbsp;throws&nbsp;InterruptedException&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;result&nbsp;=&nbsp;cache.get(arg);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(result&nbsp;==&nbsp;null)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;c.compute(arg);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.put(arg,&nbsp;result);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;result;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">public class Memoizer2&lt;A, V&gt; implements Computable&lt;A, V&gt; {
private final Map&lt;A, V&gt; cache = new ConcurrentHashMap&lt;A, V&gt;();
private final Computable&lt;A, V&gt; c;
public Memoizer2(Computable&lt;A, V&gt; c) { this.c = c; }
public V compute(A arg) throws InterruptedException {
V result = cache.get(arg);
if (result == null) {
result = c.compute(arg);
cache.put(arg, result);
}
return result;
}
}
</pre>
<br />
将线程安全性委给cache，注：这个方案的cache用了ConcurrentHashMap，它是线程安全的。
<br />
<br />
备忘录缓存方案三：
<br />
<div>
<div>
<div>Java代码&nbsp;</div>
</div>
<ol start="1">
    <li>public&nbsp;class&nbsp;Memoizer3&lt;A,&nbsp;V&gt;&nbsp;implements&nbsp;Computable&lt;A,&nbsp;V&gt;&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;Map&lt;A,&nbsp;Future&lt;V&gt;&gt;&nbsp;cache&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;new&nbsp;ConcurrentHashMap&lt;A,&nbsp;Future&lt;V&gt;&gt;();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;Computable&lt;A,&nbsp;V&gt;&nbsp;c;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Memoizer3(Computable&lt;A,&nbsp;V&gt;&nbsp;c)&nbsp;{&nbsp;this.c&nbsp;=&nbsp;c;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;V&nbsp;compute(final&nbsp;A&nbsp;arg)&nbsp;throws&nbsp;InterruptedException&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Future&lt;V&gt;&nbsp;f&nbsp;=&nbsp;cache.get(arg);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(f&nbsp;==&nbsp;null)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Callable&lt;V&gt;&nbsp;eval&nbsp;=&nbsp;new&nbsp;Callable&lt;V&gt;()&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;V&nbsp;call()&nbsp;throws&nbsp;InterruptedException&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;c.compute(arg);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FutureTask&lt;V&gt;&nbsp;ft&nbsp;=&nbsp;new&nbsp;FutureTask&lt;V&gt;(eval);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f&nbsp;=&nbsp;ft;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.put(arg,&nbsp;ft);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ft.run();&nbsp;//&nbsp;call&nbsp;to&nbsp;c.compute&nbsp;happens&nbsp;here&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;f.get();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(ExecutionException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;launderThrowable(e.getCause());&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<pre style="display: none;" name="code" class="java">public class Memoizer3&lt;A, V&gt; implements Computable&lt;A, V&gt; {
private final Map&lt;A, Future&lt;V&gt;&gt; cache
= new ConcurrentHashMap&lt;A, Future&lt;V&gt;&gt;();
private final Computable&lt;A, V&gt; c;
public Memoizer3(Computable&lt;A, V&gt; c) { this.c = c; }
public V compute(final A arg) throws InterruptedException {
Future&lt;V&gt; f = cache.get(arg);
if (f == null) {
Callable&lt;V&gt; eval = new Callable&lt;V&gt;() {
public V call() throws InterruptedException {
return c.compute(arg);
}
};
FutureTask&lt;V&gt; ft = new FutureTask&lt;V&gt;(eval);
f = ft;
cache.put(arg, ft);
ft.run(); // call to c.compute happens here
}
try {
return f.get();
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
}
}
}
</pre>
<br />
使用Future(相当上一帖的Entry)封装，因为这里资源获取过程不固定(通用方案)，所以使用了Callable进行回调资源获取过程(求值)，
<br />
这个方案的 if (f == null) 不安全，特殊性可能会进行多次运算，下面的方案四解决这个问题。
<br />
<br />
备忘录缓存方案四（最终方案）：
<br />
<div>
<div>
<div>Java代码&nbsp;</div>
</div>
<ol start="1">
    <li>public&nbsp;class&nbsp;Memoizer&lt;A,&nbsp;V&gt;&nbsp;implements&nbsp;Computable&lt;A,&nbsp;V&gt;&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;ConcurrentMap&lt;A,&nbsp;Future&lt;V&gt;&gt;&nbsp;cache&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;new&nbsp;ConcurrentHashMap&lt;A,&nbsp;Future&lt;V&gt;&gt;();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;Computable&lt;A,&nbsp;V&gt;&nbsp;c;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Memoizer(Computable&lt;A,&nbsp;V&gt;&nbsp;c)&nbsp;{&nbsp;this.c&nbsp;=&nbsp;c;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;V&nbsp;compute(final&nbsp;A&nbsp;arg)&nbsp;throws&nbsp;InterruptedException&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(true)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Future&lt;V&gt;&nbsp;f&nbsp;=&nbsp;cache.get(arg);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(f&nbsp;==&nbsp;null)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Callable&lt;V&gt;&nbsp;eval&nbsp;=&nbsp;new&nbsp;Callable&lt;V&gt;()&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;V&nbsp;call()&nbsp;throws&nbsp;InterruptedException&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;c.compute(arg);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FutureTask&lt;V&gt;&nbsp;ft&nbsp;=&nbsp;new&nbsp;FutureTask&lt;V&gt;(eval);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f&nbsp;=&nbsp;cache.putIfAbsent(arg,&nbsp;ft);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(f&nbsp;==&nbsp;null)&nbsp;{&nbsp;f&nbsp;=&nbsp;ft;&nbsp;ft.run();&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;f.get();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(CancellationException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.remove(arg,&nbsp;f);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(ExecutionException&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;launderThrowable(e.getCause());&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>}&nbsp; <br />
    </li>
</ol>
</div>
<img src ="http://www.blogjava.net/java-blog/aggbug/191992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-04-10 22:30 <a href="http://www.blogjava.net/java-blog/articles/191992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java]用OSCache进行缓存对象</title><link>http://www.blogjava.net/java-blog/articles/191952.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Thu, 10 Apr 2008 10:13:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/191952.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/191952.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/191952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/191952.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/191952.html</trackback:ping><description><![CDATA[Java]用OSCache进行缓存对象<br />
<br />
<strong>1、OSCache是什么?</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;
OSCache标记库由OpenSymphony设计，它是一种开创性的缓存方案，它提供了在现有JSP页面之内实现内存缓存的功能。OSCache是个
一个被广泛采用的高性能的J2EE缓存框架，OSCache还能应用于任何Java应用程序的普通的缓存解决方案。<br />
<strong>2、OSCache的特点</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;(1) 缓存任何对象：你可以不受限制的缓存部分jsp页面或HTTP请求，任何java对象都可以缓存。<br />
&nbsp;&nbsp;&nbsp;&nbsp;(2) 拥有全面的API：OSCache API允许你通过编程的方式来控制所有的OSCache特性。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;(3) 永久缓存：缓存能被配置写入硬盘，因此允许在应用服务器的多次生命周期间缓存创建开销昂贵的数据。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;(4) 支持集群：集群缓存数据能被单个的进行参数配置，不需要修改代码。<br />
&nbsp;&nbsp;&nbsp;&nbsp;(5) 缓存过期：你可以有最大限度的控制缓存对象的过期，包括可插入式的刷新策略（如果默认性能不能满足需要时）。<br />
<strong>3、OSCache的安装与配置</strong> <br />
&nbsp;&nbsp;&nbsp;&nbsp;网上已经有一个不错的使用教程：<a href="http://blog.csdn.net/ezerg/archive/2004/10/14/135769.aspx" target="_blank">http://blog.csdn.net/ezerg/archive/2004/10/14/135769.aspx </a><br />
<strong>4、有关&#8220;用OSCache进行缓存对象&#8221;的研究</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;这个是我今天要说的东西。网上对于OSCache缓存Web页面很多说明和例子，但对于缓存对象方面说得不多，我就把自已写得一些东西放出来，让大家看一看是怎样缓存对象的!<br />
&nbsp;&nbsp;&nbsp; 我基于GeneralCacheAdministrator类来写的BaseCache类<br />
&nbsp;&nbsp;&nbsp;
<div>
<div>
<div><a nclick="dp.sh.Toolbar.Command('ViewSource',this);return false;" href="http://www.klstudio.com/post/123.html#">view plain</a><a nclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.klstudio.com/post/123.html#">copy to clipboard</a><a nclick="dp.sh.Toolbar.Command('PrintSource',this);return false;" href="http://www.klstudio.com/post/123.html#">print</a><a nclick="dp.sh.Toolbar.Command('About',this);return false;" href="http://www.klstudio.com/post/123.html#">?</a></div>
</div>
<ol>
    <li>package&nbsp;com.klstudio.cache; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;java.util.Date; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;com.opensymphony.oscache.base.NeedsRefreshException; &nbsp;&nbsp;</li>
    <li>import&nbsp;com.opensymphony.oscache.general.GeneralCacheAdministrator; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;BaseCache&nbsp;extends&nbsp;GeneralCacheAdministrator&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//过期时间(单位为秒); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;int&nbsp;refreshPeriod; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//关键字前缀字符; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;keyPrefix; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;long&nbsp;serialVersionUID&nbsp;=&nbsp;-4397192926052141162L; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;BaseCache(String&nbsp;keyPrefix,int&nbsp;refreshPeriod){ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.keyPrefix&nbsp;=&nbsp;keyPrefix; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.refreshPeriod&nbsp;=&nbsp;refreshPeriod; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//添加被缓存的对象; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;put(String&nbsp;key,Object&nbsp;value){ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.putInCache(this.keyPrefix+"_"+key,value); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//删除被缓存的对象; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;remove(String&nbsp;key){ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.flushEntry(this.keyPrefix+"_"+key); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//删除所有被缓存的对象; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;removeAll(Date&nbsp;date){ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.flushAll(date); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;removeAll(){ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.flushAll(); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//获取被缓存的对象; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Object&nbsp;get(String&nbsp;key)&nbsp;throws&nbsp;Exception{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;this.getFromCache(this.keyPrefix+"_"+key,this.refreshPeriod); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(NeedsRefreshException&nbsp;e)&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.cancelUpdate(this.keyPrefix+"_"+key); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;e; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</li>
    <li>} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
</ol>
</div>
<textarea style="display: none;" name="code">package com.klstudio.cache;
import java.util.Date;
import com.opensymphony.oscache.base.NeedsRefreshException;
import com.opensymphony.oscache.general.GeneralCacheAdministrator;
public class BaseCache extends GeneralCacheAdministrator {
//过期时间(单位为秒);
private int refreshPeriod;
//关键字前缀字符;
private String keyPrefix;
private static final long serialVersionUID = -4397192926052141162L;
public BaseCache(String keyPrefix,int refreshPeriod){
super();
this.keyPrefix = keyPrefix;
this.refreshPeriod = refreshPeriod;
}
//添加被缓存的对象;
public void put(String key,Object value){
this.putInCache(this.keyPrefix+"_"+key,value);
}
//删除被缓存的对象;
public void remove(String key){
this.flushEntry(this.keyPrefix+"_"+key);
}
//删除所有被缓存的对象;
public void removeAll(Date date){
this.flushAll(date);
}
public void removeAll(){
this.flushAll();
}
//获取被缓存的对象;
public Object get(String key) throws Exception{
try{
return this.getFromCache(this.keyPrefix+"_"+key,this.refreshPeriod);
} catch (NeedsRefreshException e) {
this.cancelUpdate(this.keyPrefix+"_"+key);
throw e;
}
}
}
</textarea> <br />
&nbsp;&nbsp; 通过CacheManager类来看怎样缓存对象的,这个类中所用的News只是具体功能的类，我就不贴出来了，你可以自己写一个!<br />
&nbsp;&nbsp;&nbsp;
<div>
<div>
<div><a nclick="dp.sh.Toolbar.Command('ViewSource',this);return false;" href="http://www.klstudio.com/post/123.html#">view plain</a><a nclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.klstudio.com/post/123.html#">copy to clipboard</a><a nclick="dp.sh.Toolbar.Command('PrintSource',this);return false;" href="http://www.klstudio.com/post/123.html#">print</a><a nclick="dp.sh.Toolbar.Command('About',this);return false;" href="http://www.klstudio.com/post/123.html#">?</a></div>
</div>
<ol>
    <li>package&nbsp;com.klstudio; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>import&nbsp;com.klstudio.News; &nbsp;&nbsp;</li>
    <li>import&nbsp;com.klstudio.cache.BaseCache; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;CacheManager&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;BaseCache&nbsp;newsCache; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;CacheManager&nbsp;instance; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;Object&nbsp;lock&nbsp;=&nbsp;new&nbsp;Object(); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;CacheManager()&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//这个根据配置文件来，初始BaseCache而已; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newsCache&nbsp;=&nbsp;new&nbsp;BaseCache("news",1800);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;CacheManager&nbsp;getInstance(){ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(instance&nbsp;==&nbsp;null){ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;synchronized(&nbsp;lock&nbsp;){ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(instance&nbsp;==&nbsp;null){ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;instance&nbsp;=&nbsp;new&nbsp;CacheManager(); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;instance; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;putNews(News&nbsp;news)&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;TODO&nbsp;自动生成方法存根 &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newsCache.put(news.getID(),news); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;removeNews(String&nbsp;newsID)&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;TODO&nbsp;自动生成方法存根 &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newsCache.remove(newsID); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;News&nbsp;getNews(String&nbsp;newsID)&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;TODO&nbsp;自动生成方法存根 &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(News)&nbsp;newsCache.get(newsID); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;TODO&nbsp;自动生成&nbsp;catch&nbsp;块 &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("getNews&gt;&gt;newsID["+newsID+"]&gt;&gt;"+e.getMessage()); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;News&nbsp;news&nbsp;=&nbsp;new&nbsp;News(newsID); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.putNews(news); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;news; &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;removeAllNews()&nbsp;{ &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;TODO&nbsp;自动生成方法存根 &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newsCache.removeAll(); &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
    <li>} &nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;</li>
</ol>
</div>
<textarea style="display: none;" name="code">package com.klstudio;
import com.klstudio.News;
import com.klstudio.cache.BaseCache;
public class CacheManager {
private BaseCache newsCache;
private static CacheManager instance;
private static Object lock = new Object();
public CacheManager() {
//这个根据配置文件来，初始BaseCache而已;
newsCache = new BaseCache("news",1800);
}
public static CacheManager getInstance(){
if (instance == null){
synchronized( lock ){
if (instance == null){
instance = new CacheManager();
}
}
}
return instance;
}
public void putNews(News news) {
// TODO 自动生成方法存根
newsCache.put(news.getID(),news);
}
public void removeNews(String newsID) {
// TODO 自动生成方法存根
newsCache.remove(newsID);
}
public News getNews(String newsID) {
// TODO 自动生成方法存根
try {
return (News) newsCache.get(newsID);
} catch (Exception e) {
// TODO 自动生成 catch 块
System.out.println("getNews&gt;&gt;newsID["+newsID+"]&gt;&gt;"+e.getMessage());
News news = new News(newsID);
this.putNews(news);
return news;
}
}
public void removeAllNews() {
// TODO 自动生成方法存根
newsCache.removeAll();
}
}
</textarea>
<img src ="http://www.blogjava.net/java-blog/aggbug/191952.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-04-10 18:13 <a href="http://www.blogjava.net/java-blog/articles/191952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA STRING FORMAT 简介</title><link>http://www.blogjava.net/java-blog/articles/189040.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Thu, 27 Mar 2008 08:09:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/189040.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/189040.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/189040.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/189040.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/189040.html</trackback:ping><description><![CDATA[<p><span style="font-size: 10.5pt;">JDK1.5中，String类新增了一个很有用的静态方法String.format():<br />
format(Locale l, String format, Object... args) 使用指定的语言环境、格式字符串和参数返回一个格式化字符串。<br />
format(String format, Object... args) 使用指定的格式字符串和参数返回一个格式化字符串。<br />
<br />
举几个这个方法实用的例子(注释是输出结果)： </span></p>
<p style="margin: 1em 1em 0px; font-weight: bold;">CODE:</p>
<p><code style="border: 1px solid #cccccc; margin: 0px 1em 1em; padding: 0.5em; display: block; font-family: Courier,monospace; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: 1.8em; font-size-adjust: none; font-stretch: normal;">long now = System.currentTimeMillis();<br />
<br />
String s = String.format("%tR", now);&nbsp;&nbsp; // "15:12"</code></p>
<p style="margin: 1em 1em 0px; font-weight: bold;">CODE:</p>
<p><code style="border: 1px solid #cccccc; margin: 0px 1em 1em; padding: 0.5em; display: block; font-family: Courier,monospace; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: 1.8em; font-size-adjust: none; font-stretch: normal;">// Current month/day/year<br />
<br />
Date d = new Date(now);<br />
<br />
s = String.format("%tD", d); &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; // "07/13/04"</code></p>
<p style="margin: 1em 1em 0px; font-weight: bold;">CODE:</p>
<p><code style="border: 1px solid #cccccc; margin: 0px 1em 1em; padding: 0.5em; display: block; font-family: Courier,monospace; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: 1.8em; font-size-adjust: none; font-stretch: normal;">s = String.format("%,d", Integer.MAX_VALUE); // "2,147,483,647"</code></p>
<p style="margin: 1em 1em 0px; font-weight: bold;">CODE:</p>
<p><code style="border: 1px solid #cccccc; margin: 0px 1em 1em; padding: 0.5em; display: block; font-family: Courier,monospace; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: 1.8em; font-size-adjust: none; font-stretch: normal;">s = String.format("%05d", 123); &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // "00123"</code>是不是很方便，让人动心啊？哈哈，还有更多的效果!<br />
<br />
其
实format函数有些类似c语言中printf函数，一些格式字符串与 C 类似，但已进行了某些定制，以适应 Java
语言，并且利用了其中一些特性。此方法提供了对布局对齐和排列的支持，以及对数值、字符串和日期/时间数据的常规格式和特定于语言环境的输出的支持。支持
诸如 byte、BigDecimal 和 Calendar 等常见 Java 类型。<br />
<br />
产生格式化输出的每个方法都需要格式字符串 和参数列表。格式字符串是一个 String，它可以包含固定文本以及一个或多个嵌入的格式说明符。请考虑以下示例：<br />
<br />
Calendar c = ...;<br />
String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);<br />
<br />
格
式字符串是 format 方法的第一个参数。它包含三个格式说明符 "%1$tm"、"%1$te" 和
"%1$tY"，它们指出应该如何处理参数以及在文本的什么地方插入它们。格式字符串的其余部分是包括 "Dukes Birthday: "
和其他任何空格或标点符号的固定文本。 参数列表由传递给位于格式字符串之后的方法的所有参数组成。在上述示例中，参数列表的大小为 1，由新对象
Calendar 组成。<br />
<br />
<strong>1.常规类型、字符类型和数值类型的格式说明符的语法如下：</strong>%[argument_index$][flags][width][.precision]conversion<br />
<br />
可选的 <em>argument_index</em> 是一个十进制整数，用于表明参数在参数列表中的位置。第一个参数由 "1$" 引用，第二个参数由 "2$" 引用，依此类推。<br />
可选的 <em>flags</em> 是修改输出格式的字符集。有效标志的集合取决于转换类型。<br />
可选 <em>width</em> 是一个非负十进制整数，表明要向输出中写入的最少字符数。<br />
可选 <em>precision</em> 是一个非负十进制整数，通常用来限制字符数。特定行为取决于转换类型。<br />
所需的 <em>conversion</em> 是一个表明应该如何格式化参数的字符。给定参数的有效转换集合取决于参数的数据类型。<br />
<br />
<strong>2.用来表示日期和时间类型的格式说明符的语法如下:</strong><br />
%[argument_index$][flags][width]conversion<br />
<br />
可选的 <em>argument_index</em>、<em>flags</em> 和 <em>width</em> 的定义同上。<br />
所需的 <em>conversion</em> 是一个由两字符组成的序列。第一个字符是 't' 或 'T'。第二个字符表明所使用的格式。这些字符类似于但不完全等同于那些由 GNU date 和 POSIX strftime(3c) 定义的字符。 <br />
<br />
<br />
<strong>3.与参数不对应的格式说明符的语法如下：</strong><br />
%[flags][width]conversion<br />
<br />
可选 <em>flags</em> 和 <em>width</em> 的定义同上。<br />
所需的 <em>conversion</em> 是一个表明要在输出中所插内容的字符。 <br />
<br />
<font size="4"><strong>转换</strong></font><br />
转换可分为以下几类：<br />
1. 常规 - 可应用于任何参数类型<br />
2.
字符 - 可应用于表示 Unicode 字符的基本类型：char、Character、byte、Byte、short 和 Short。当
Character.isValidCodePoint(int) 返回 true 时，可将此转换应用于 int 和 Integer 类型<br />
3. 数值<br />
&nbsp;&nbsp; &nbsp;&nbsp; 1. 整数 - 可应用于 Java 的整数类型：byte、Byte、short、Short、int、Integer、long、Long 和 BigInteger<br />
&nbsp;&nbsp; &nbsp;&nbsp; 2. 浮点 - 可用于 Java 的浮点类型：float、Float、double、Double 和 BigDecimal <br />
4. 日期/时间 - 可应用于 Java 的、能够对日期或时间进行编码的类型：long、Long、Calendar 和 Date。<br />
5. 百分比 - 产生字面值 '%' ('"u0025')<br />
6. 行分隔符 - 产生特定于平台的行分隔符<br />
<br />
下
表总结了受支持的转换。由大写字符（如 'B'、'H'、'S'、'C'、'X'、'E'、'G'、'A' 和
'T'）表示的转换与由相应的小写字符的转换等同，根据流行的 Locale 规则将结果转换为大写形式除外。后者等同于
String.toUpperCase() 的以下调用.<br />
<br />
</p>
<table align="center" cellspacing="0">
    <tbody>
        <tr>
            <td>转换</td>
            <td>参数类别</td>
            <td>说明</td>
        </tr>
        <tr>
            <td>'b', 'B' </td>
            <td>常规 </td>
            <td>如果参数 <em>arg</em> 为 null，则结果为 "false"。如果 <em>arg</em> 是一个 boolean 值或 <a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/lang/Boolean.html" target="_blank">Boolean</a>，则结果为 <a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/lang/String.html#valueOf%28boolean%29" target="_blank">String.valueOf()</a> 返回的字符串。否则结果为 "true"。</td>
        </tr>
        <tr>
            <td>'h', 'H' </td>
            <td>常规 </td>
            <td>如果参数 <em>arg</em> 为 null，则结果为 "null"。否则，结果为调用 Integer.toHexString(arg.hashCode()) 得到的结果。</td>
        </tr>
        <tr>
            <td>'s', 'S' </td>
            <td>常规 </td>
            <td>如果参数 <em>arg</em> 为 null，则结果为 "null"。如果 <em>arg</em> 实现 <a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/util/Formattable.html" target="_blank">Formattable</a>，则调用 <a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/util/Formattable.html#formatTo%28java.util.Formatter,%20int,%20int,%20int%29" target="_blank">arg.formatTo</a>。否则，结果为调用 arg.toString() 得到的结果。</td>
        </tr>
        <tr>
            <td>'c', 'C' </td>
            <td>字符 </td>
            <td>结果是一个 Unicode 字符</td>
        </tr>
        <tr>
            <td>'d' </td>
            <td>整数 </td>
            <td>结果被格式化为十进制整数</td>
        </tr>
        <tr>
            <td>'o' </td>
            <td>整数 </td>
            <td>结果被格式化为八进制整数</td>
        </tr>
        <tr>
            <td>'x', 'X' </td>
            <td>整数 </td>
            <td>结果被格式化为十六进制整数</td>
        </tr>
        <tr>
            <td>'e', 'E' </td>
            <td>浮点 </td>
            <td>结果被格式化为用计算机科学记数法表示的十进制数</td>
        </tr>
        <tr>
            <td>'f' </td>
            <td>浮点 </td>
            <td>结果被格式化为十进制数</td>
        </tr>
        <tr>
            <td>'g', 'G' </td>
            <td>浮点 </td>
            <td>根据精度和舍入运算后的值，使用计算机科学记数形式或十进制格式对结果进行格式化。</td>
        </tr>
        <tr>
            <td>'a', 'A' </td>
            <td>浮点 </td>
            <td>结果被格式化为带有效位数和指数的十六进制浮点数</td>
        </tr>
        <tr>
            <td>'t', 'T' </td>
            <td>日期/时间 </td>
            <td>日期和时间转换字符的前缀。请参阅<a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/util/Formatter.html#dt" target="_blank">日期/时间转换</a>。</td>
        </tr>
        <tr>
            <td>'%' </td>
            <td>百分比 </td>
            <td>结果为字面值 '%' ('"u0025')</td>
        </tr>
        <tr>
            <td>'n' </td>
            <td>行分隔符 </td>
            <td>结果为特定于平台的行分隔符</td>
        </tr>
    </tbody>
</table>
<br />
任何未明确定义为转换的字符都是非法字符，并且都被保留，以供将来扩展使用。<br />
<br />
<font size="4"><strong>日期/时间转换<br />
</strong></font>以
下日期和时间转换的后缀字符是为 't' 和 'T' 转换定义的。这些类型相似于但不完全等同于那些由 GNU date 和 POSIX
strftime(3c) 定义的类型。提供其他转换类型是为了访问特定于 Java 的功能（如将 'L' 用作秒中的毫秒）。<br />
<br />
以下转换字符用来格式化时间：<br />
<br />
<table align="center" cellspacing="0">
    <tbody>
        <tr>
            <td>'H' </td>
            <td>24 小时制的小时，被格式化为必要时带前导零的两位数，即 00 - 23。</td>
        </tr>
        <tr>
            <td>'I' </td>
            <td>12 小时制的小时，被格式化为必要时带前导零的两位数，即 01 - 12。</td>
        </tr>
        <tr>
            <td>'k' </td>
            <td>24 小时制的小时，即 0 - 23。</td>
        </tr>
        <tr>
            <td>'l' </td>
            <td>12 小时制的小时，即 1 - 12。</td>
        </tr>
        <tr>
            <td>'M' </td>
            <td>小时中的分钟，被格式化为必要时带前导零的两位数，即 00 - 59。</td>
        </tr>
        <tr>
            <td>'S' </td>
            <td>分钟中的秒，被格式化为必要时带前导零的两位数，即 00 - 60 （"60" 是支持闰秒所需的一个特殊值）。</td>
        </tr>
        <tr>
            <td>'L' </td>
            <td>秒中的毫秒，被格式化为必要时带前导零的三位数，即 000 - 999。</td>
        </tr>
        <tr>
            <td>'N' </td>
            <td>秒中的毫微秒，被格式化为必要时带前导零的九位数，即 000000000 - 999999999。</td>
        </tr>
        <tr>
            <td>'p' </td>
            <td>特定于语言环境的 <a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/text/DateFormatSymbols.html#getAmPmStrings%28%29" target="_blank">上午或下午</a> 标记以小写形式表示，例如 "am" 或 "pm"。使用转换前缀 'T' 可以强行将此输出转换为大写形式。</td>
        </tr>
        <tr>
            <td>'z' </td>
            <td>相对于 GMT 的 <a href="http://www.ietf.org/rfc/rfc0822.txt" target="_blank">RFC 822</a> 格式的数字时区偏移量，例如 -0800。</td>
        </tr>
        <tr>
            <td>'Z' </td>
            <td>表示时区缩写形式的字符串。Formatter 的语言环境将取代参数的语言环境（如果有）。</td>
        </tr>
        <tr>
            <td>'s' </td>
            <td>自协调世界时 (UTC) 1970 年 1 月 1 日 00:00:00 至现在所经过的秒数，即 Long.MIN_VALUE/1000 与 Long.MAX_VALUE/1000 之间的差值。</td>
        </tr>
        <tr>
            <td>'Q' </td>
            <td>自协调世界时 (UTC) 1970 年 1 月 1 日 00:00:00 至现在所经过的毫秒数，即 Long.MIN_VALUE 与 Long.MAX_VALUE 之间的差值。</td>
        </tr>
    </tbody>
</table>
<br />
以下转换字符用来格式化日期： <br />
<br />
<table align="center" cellspacing="0">
    <tbody>
        <tr>
            <td>'B' </td>
            <td>特定于语言环境的<a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/text/DateFormatSymbols.html#getMonths%28%29" target="_blank">月份全称</a>，例如 "January" 和 "February"。</td>
        </tr>
        <tr>
            <td>'b' </td>
            <td>特定于语言环境的<a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/text/DateFormatSymbols.html#getShortMonths%28%29" target="_blank">月份简称</a>，例如 "Jan" 和 "Feb"。</td>
        </tr>
        <tr>
            <td>'h' </td>
            <td>与 'b' 相同。</td>
        </tr>
        <tr>
            <td>'A' </td>
            <td>特定于语言环境的<a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/text/DateFormatSymbols.html#getWeekdays%28%29" target="_blank">星期几</a>全称，例如 "Sunday" 和 "Monday"</td>
        </tr>
        <tr>
            <td>'a' </td>
            <td>特定于语言环境的<a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/text/DateFormatSymbols.html#getShortWeekdays%28%29" target="_blank">星期几</a>简称，例如 "Sun" 和 "Mon"</td>
        </tr>
        <tr>
            <td>'C' </td>
            <td>除以 100 的四位数表示的年份，被格式化为必要时带前导零的两位数，即 00 - 99</td>
        </tr>
        <tr>
            <td>'Y' </td>
            <td>年份，被格式化为必要时带前导零的四位数（至少），例如，0092 等于格里高利历的 92 CE。</td>
        </tr>
        <tr>
            <td>'y' </td>
            <td>年份的最后两位数，被格式化为必要时带前导零的两位数，即 00 - 99。</td>
        </tr>
        <tr>
            <td>'j' </td>
            <td>一年中的天数，被格式化为必要时带前导零的三位数，例如，对于格里高利历是 001 - 366。</td>
        </tr>
        <tr>
            <td>'m' </td>
            <td>月份，被格式化为必要时带前导零的两位数，即 01 - 13。</td>
        </tr>
        <tr>
            <td>'d' </td>
            <td>一个月中的天数，被格式化为必要时带前导零两位数，即 01 - 31</td>
        </tr>
        <tr>
            <td>'e' </td>
            <td>一个月中的天数，被格式化为两位数，即 1 - 31。</td>
        </tr>
    </tbody>
</table>
<br />
以下转换字符用于格式化常见的日期/时间组合。 <br />
<br />
<table align="center" cellspacing="0">
    <tbody>
        <tr>
            <td>'R' </td>
            <td>24 小时制的时间，被格式化为 "%tH:%tM"</td>
        </tr>
        <tr>
            <td>'T' </td>
            <td>24 小时制的时间，被格式化为 "%tH:%tM:%tS"。</td>
        </tr>
        <tr>
            <td>'r' </td>
            <td>12 小时制的时间，被格式化为 "%tI:%tM:%tS %Tp"。上午或下午标记 ('%Tp') 的位置可能与语言环境有关。</td>
        </tr>
        <tr>
            <td>'D' </td>
            <td>日期，被格式化为 "%tm/%td/%ty"。</td>
        </tr>
        <tr>
            <td>'F' </td>
            <td><a href="http://www.w3.org/TR/NOTE-datetime" target="_blank">ISO 8601</a> 格式的完整日期，被格式化为 "%tY-%tm-%td"。</td>
        </tr>
        <tr>
            <td>'c' </td>
            <td>日期和时间，被格式化为 "%ta %tb %td %tT %tZ %tY"，例如 "Sun Jul 20 16:17:00 EDT 1969"。</td>
        </tr>
    </tbody>
</table>
<br />
任何未明确定义为转换的字符都是非法字符，并且都被保留，以供将来扩展使用。<br />
<br />
<font size="4"><strong><br />
标志</strong></font><br />
下表总结了受支持的标志。y 表示该标志受指示参数类型支持。 <br />
<br />
<table align="center" cellspacing="0">
    <tbody>
        <tr>
            <td>标志</td>
            <td>常规</td>
            <td>字符</td>
            <td>整数</td>
            <td>浮点</td>
            <td>日期/时间</td>
            <td>说明</td>
        </tr>
        <tr>
            <td>'-'</td>
            <td>y &nbsp;&nbsp;&nbsp;</td>
            <td>y &nbsp;&nbsp;&nbsp;</td>
            <td>y &nbsp;&nbsp;&nbsp;</td>
            <td>y &nbsp;&nbsp;&nbsp;</td>
            <td>y</td>
            <td>结果将是左对齐的。</td>
        </tr>
        <tr>
            <td>'#'</td>
            <td>y1 &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>y3 &nbsp;&nbsp;&nbsp;</td>
            <td>y &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>结果应该使用依赖于转换类型的替换形式</td>
        </tr>
        <tr>
            <td>'+'</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>y4 &nbsp;&nbsp;&nbsp;</td>
            <td>y &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>结果总是包括一个符号</td>
        </tr>
        <tr>
            <td>'&nbsp;&nbsp; '</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>y4 &nbsp;&nbsp;&nbsp;</td>
            <td>y &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>对于正值，结果中将包括一个前导空格</td>
        </tr>
        <tr>
            <td>'0'</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>y &nbsp;&nbsp;&nbsp;</td>
            <td>y &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>结果将用零来填充</td>
        </tr>
        <tr>
            <td>','</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>y2 &nbsp;&nbsp;&nbsp;</td>
            <td>y5 &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>结果将包括特定于语言环境的<a href="http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/text/DecimalFormatSymbols.html#getGroupingSeparator%28%29" target="_blank">组分隔符</a></td>
        </tr>
        <tr>
            <td>'('</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>y4 &nbsp;&nbsp;&nbsp;</td>
            <td>y5 &nbsp;&nbsp;&nbsp;</td>
            <td>- &nbsp;&nbsp;&nbsp;</td>
            <td>结果将是用圆括号括起来的负数</td>
        </tr>
    </tbody>
</table>
<br />
1 取决于 Formattable 的定义。<br />
<br />
2 只适用于 'd' 转换。<br />
<br />
3 只适用于 'o'、'x' 和 'X' 转换。<br />
<br />
4 对 BigInteger 应用 'd'、'o'、'x' 和 'X' 转换时，或者对 byte 及 Byte、short 及 Short、int 及 Integer、long 及 Long 分别应用 'd' 转换时适用。<br />
<br />
5 只适用于 'e'、'E'、'f'、'g' 和 'G' 转换。<br />
<br />
任何未显式定义为标志的字符都是非法字符，并且都被保留，以供扩展使用。 <br />
<br />
宽度&nbsp;&nbsp; 宽度是将向输出中写入的最少字符数。对于行分隔符转换，不适用宽度，如果提供宽度，则会抛出异常。<br />
精度&nbsp;&nbsp; 对于常规参数类型，精度是将向输出中写入的最多字符数。<br />
对于浮点转换 'e'、'E' 和 'f'，精度是小数点分隔符后的位数。如果转换是 'g' 或 'G'，那么精度是舍入计算后所得数值的所有位数。如果转换是 'a' 或 'A'，则不必指定精度。<br />
对于字符、整数和日期/时间参数类型转换，以及百分比和行分隔符转换，精度是不适用的；如果提供精度，则会抛出异常。<br />
参数索引&nbsp;&nbsp; 参数索引是一个十进制整数，用于表明参数在参数列表中的位置。第一个参数由 "1$" 引用，第二个参数由 "2$" 引用，依此类推。<br />
根据位置引用参数的另一种方法是使用 '&lt;' ('"u003c') 标志，这将会重用以前格式说明符的参数。例如，以下两条语句产生的字符相同：
<blockquote>Calendar c = ...;<br />
String s1 = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);<br />
<br />
String s2 = String.format("Duke's Birthday: %1$tm %&lt;$te,%&lt;$tY", c);</blockquote>
<img src ="http://www.blogjava.net/java-blog/aggbug/189040.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-03-27 16:09 <a href="http://www.blogjava.net/java-blog/articles/189040.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4j配置</title><link>http://www.blogjava.net/java-blog/articles/180369.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Sun, 17 Feb 2008 15:51:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/180369.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/180369.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/180369.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/180369.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/180369.html</trackback:ping><description><![CDATA[og4j.properties 使用
<div>一.参数意义说明 </div>
<div>输出级别的种类 </div>
<div>ERROR、WARN、INFO、DEBUG </div>
<div>ERROR 为严重错误 主要是程序的错误 </div>
<div>WARN 为一般警告，比如session丢失 </div>
<div>INFO 为一般要显示的信息，比如登录登出 </div>
<div>DEBUG 为程序的调试信息 </div>
<div>配置日志信息输出目的地 </div>
<div>log4j.appender.appenderName = fully.qualified.name.of.appender.class </div>
<div>1.org.apache.log4j.ConsoleAppender（控制台） </div>
<div>2.org.apache.log4j.FileAppender（文件） </div>
<div>3.org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件） </div>
<div>4.org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件） </div>
<div>5.org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方） </div>
<div>&#173;</div>
<div>配置日志信息的格式 </div>
<div>log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class </div>
<div>1.org.apache.log4j.HTMLLayout（以HTML表格形式布局）， </div>
<div>2.org.apache.log4j.PatternLayout（可以灵活地指定布局模式）， </div>
<div>3.org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串）， </div>
<div>4.org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息） </div>
<div>控制台选项 </div>
<div>Threshold=DEBUG:指定日志消息的输出最低层次。 </div>
<div>ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 </div>
<div>Target=System.err：默认情况下是：System.out,指定输出控制台 </div>
<div>FileAppender 选项 </div>
<div>Threshold=DEBUF:指定日志消息的输出最低层次。 </div>
<div>ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 </div>
<div>File=mylog.txt:指定消息输出到mylog.txt文件。 </div>
<div>Append=false:默认值是true,即将消息增加到指定文件中，false指将消息覆盖指定的文件内容。 </div>
<div>RollingFileAppender 选项 </div>
<div>Threshold=DEBUG:指定日志消息的输出最低层次。 </div>
<div>ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。 </div>
<div>File=mylog.txt:指定消息输出到mylog.txt文件。 </div>
<div>Append=false:默认值是true,即将消息增加到指定文件中，false指将消息覆盖指定的文件内容。 </div>
<div>MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时，将会自动滚动，即将原来的内容移到mylog.log.1文件。 </div>
<div>MaxBackupIndex=2:指定可以产生的滚动文件的最大数。 </div>
<div>log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n </div>
<div>日志信息格式中几个符号所代表的含义： </div>
<div>-X号: X信息输出时左对齐； </div>
<div>%p: 输出日志信息优先级，即DEBUG，INFO，WARN，ERROR，FATAL, </div>
<div>%d: 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921 </div>
<div>%r: 输出自应用启动到输出该log信息耗费的毫秒数 </div>
<div>%c: 输出日志信息所属的类目，通常就是所在类的全名 </div>
<div>%t: 输出产生该日志事件的线程名 </div>
<div>%l: 输出日志事件的发生位置，相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程，以及在代码中的行数。举例：Testlog4.main (TestLog4.java:10) </div>
<div>%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。 </div>
<div>%%: 输出一个"%"字符 </div>
<div>%F: 输出日志消息产生时所在的文件名称 </div>
<div>%L: 输出代码中的行号 </div>
<div>%m: 输出代码中指定的消息,产生的日志具体信息 </div>
<div>%n: 输出一个回车换行符，Windows平台为""r"n"，Unix平台为""n"输出日志信息换行 </div>
<div>可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如： </div>
<div>1)%20c：指定输出category的名称，最小的宽度是20，如果category的名称小于20的话，默认的情况下右对齐。 </div>
<div>2)%-20c:指定输出category的名称，最小的宽度是20，如果category的名称小于20的话，"-"号指定左对齐。 </div>
<div>3)%.30c:指定输出category的名称，最大的宽度是30，如果category的名称大于30的话，就会将左边多出的字符截掉，但小于30的话也不会有空格。 </div>
<div>4)%20.30c:如果category的名称小于20就补空格，并且右对齐，如果其名称长于30字符，就从左边较远输出的字符截掉。 </div>
<div>二.文件配置Sample1 </div>
<div>log4j.rootLogger=DEBUG,A1,R </div>
<div>#log4j.rootLogger=INFO,A1,R </div>
<div># ConsoleAppender 输出 </div>
<div>log4j.appender.A1=org.apache.log4j.ConsoleAppender </div>
<div>log4j.appender.A1.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n </div>
<div># File 输出 一天一个文件,输出路径可以定制,一般在根路径下 </div>
<div>log4j.appender.R=org.apache.log4j.DailyRollingFileAppender </div>
<div>log4j.appender.R.File=blog_log.txt </div>
<div>log4j.appender.R.MaxFileSize=500KB </div>
<div>log4j.appender.R.MaxBackupIndex=10 </div>
<div>log4j.appender.R.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n </div>
<div>文件配置Sample2 </div>
<div>下面给出的Log4J配置文件实现了输出到控制台，文件，回滚文件，发送日志邮件，输出到数据库日志表，自定义标签等全套功能。 </div>
<div>log4j.rootLogger=DEBUG,CONSOLE,A1,im </div>
<div>#DEBUG,CONSOLE,FILE,ROLLING_FILE,MAIL,DATABASE </div>
<div>log4j.addivity.org.apache=true </div>
<div>&#173;</div>
<div>################### </div>
<div># Console Appender </div>
<div>################### </div>
<div>log4j.appender.C.apache.log4j.ConsoleAppender </div>
<div>log4j.appender.Threshold=DEBUG </div>
<div>log4j.appender.CONSOLE.Target=System.out </div>
<div>log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n </div>
<div>#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]
n%c[CATEGORY]%n%m[MESSAGE]%n%n </div>
<div>&#173;</div>
<div>##################### </div>
<div># File Appender </div>
<div>##################### </div>
<div>log4j.appender.FILE=org.apache.log4j.FileAppender </div>
<div>log4j.appender.FILE.File=file.log </div>
<div>log4j.appender.FILE.Append=false </div>
<div>log4j.appender.FILE.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n </div>
<div># Use this layout for LogFactor 5 analysis </div>
<div>&#173;</div>
<div>######################## </div>
<div># Rolling File </div>
<div>######################## </div>
<div>log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender </div>
<div>log4j.appender.ROLLING_FILE.Threshold=ERROR </div>
<div>log4j.appender.ROLLING_FILE.File=rolling.log </div>
<div>log4j.appender.ROLLING_FILE.Append=true </div>
<div>log4j.appender.ROLLING_FILE.MaxFileSize=10KB </div>
<div>log4j.appender.ROLLING_FILE.MaxBackupIndex=1 </div>
<div>log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n </div>
<div>&#173;</div>
<div>#################### </div>
<div># Socket Appender </div>
<div>#################### </div>
<div>log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender </div>
<div>log4j.appender.SOCKET.RemoteHost=localhost </div>
<div>log4j.appender.SOCKET.Port=5001 </div>
<div>log4j.appender.SOCKET.Locati </div>
<div># Set up for Log Facter 5 </div>
<div>log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n
</div>
<div>&#173;</div>
<div>######################## </div>
<div># Log Factor 5 Appender </div>
<div>######################## </div>
<div>log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender </div>
<div>log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000 </div>
<div>&#173;</div>
<div>######################## </div>
<div># SMTP Appender </div>
<div>####################### </div>
<div>log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender </div>
<div>log4j.appender.MAIL.Threshold=FATAL </div>
<div>log4j.appender.MAIL.BufferSize=10 </div>
<div><a target="_blank" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#77;&#65;&#73;&#76;&#46;&#70;&#114;&#111;&#109;&#61;&#99;&#104;&#101;&#110;&#121;&#108;&#64;&#104;&#111;&#108;&#108;&#121;&#99;&#114;&#109;&#46;&#99;&#111;&#109;">log4j.appender.MAIL.From=chenyl@hollycrm.com</a> </div>
<div>log4j.appender.MAIL.SMTPHost=mail.hollycrm.com </div>
<div>log4j.appender.MAIL.Subject=Log4J Message </div>
<div><a target="_blank" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#77;&#65;&#73;&#76;&#46;&#84;&#111;&#61;&#99;&#104;&#101;&#110;&#121;&#108;&#64;&#104;&#111;&#108;&#108;&#121;&#99;&#114;&#109;&#46;&#99;&#111;&#109;">log4j.appender.MAIL.To=chenyl@hollycrm.com</a> </div>
<div>log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n </div>
<div>&#173;</div>
<div>######################## </div>
<div># JDBC Appender </div>
<div>####################### </div>
<div>log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender </div>
<div>log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test </div>
<div>log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver </div>
<div>log4j.appender.DATABASE.user=root </div>
<div>log4j.appender.DATABASE.password= </div>
<div>log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n') </div>
<div>log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n </div>
<div>&#173;</div>
<div>log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender </div>
<div>log4j.appender.A1.File=SampleMessages.log4j </div>
<div>log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j' </div>
<div>log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout </div>
<div>################### </div>
<div>#自定义Appender </div>
<div>################### </div>
<div>log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender </div>
<div>log4j.appender.im.host = mail.cybercorlin.net </div>
<div>log4j.appender.im.username = username </div>
<div>log4j.appender.im.password = password </div>
<div>log4j.appender.im.recipient = <a target="_blank" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#99;&#111;&#114;&#108;&#105;&#110;&#64;&#99;&#121;&#98;&#101;&#114;&#99;&#111;&#114;&#108;&#105;&#110;&#46;&#110;&#101;&#116;">corlin@cybercorlin.net</a> </div>
<div>log4j.appender.im.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n </div>
<div>&#173;</div>
<div>三.高级使用 </div>
<div>实验目的： </div>
<div>1.把FATAL级错误写入2000NT日志 </div>
<div>2. WARN，ERROR，FATAL级错误发送email通知管理员 </div>
<div>3.其他级别的错误直接在后台输出 </div>
<div>&#173;</div>
<div>实验步骤： </div>
<div>输出到2000NT日志 </div>
<div>1.把Log4j压缩包里的NTEventLogAppender.dll拷到WINNT"SYSTEM32目录下 </div>
<div>2.写配置文件log4j.properties </div>
<div># 在2000系统日志输出 </div>
<div>log4j.logger.NTlog=FATAL, A8 </div>
<div># APPENDER A8 </div>
<div>log4j.appender.A8=org.apache.log4j.nt.NTEventLogAppender </div>
<div>log4j.appender.A8.Source=JavaTest </div>
<div>log4j.appender.A8.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.A8.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n </div>
<div>3.调用代码： </div>
<div>Logger logger2 = Logger.getLogger("NTlog"); //要和配置文件中设置的名字相同 </div>
<div>logger2.debug("debug!!!"); </div>
<div>logger2.info("info!!!"); </div>
<div>logger2.warn("warn!!!"); </div>
<div>logger2.error("error!!!"); </div>
<div>//只有这个错误才会写入2000日志 </div>
<div>logger2.fatal("fatal!!!"); </div>
<div>&#173;</div>
<div>发送email通知管理员： </div>
<div>1. 首先下载JavaMail和JAF, </div>
<div>&nbsp;&nbsp;<a target="_blank" href="http://java.sun.com/j2ee/ja/javamail/index.html">http://java.sun.com/j2ee/ja/javamail/index.html</a><wbr> </div>
<div>&nbsp;&nbsp;<a target="_blank" href="http://java.sun.com/beans/glasgow/jaf.html">http://java.sun.com/beans/glasgow/jaf.html</a><wbr> </div>
<div>在项目中引用mail.jar和activation.jar。 </div>
<div>2. 写配置文件 </div>
<div># 将日志发送到email </div>
<div>log4j.logger.MailLog=WARN,A5 </div>
<div>#&nbsp;&nbsp;APPENDER A5 </div>
<div>log4j.appender.A5=org.apache.log4j.net.SMTPAppender </div>
<div>log4j.appender.A5.BufferSize=5 </div>
<div><a target="_blank" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#65;&#53;&#46;&#84;&#111;&#61;&#99;&#104;&#117;&#110;&#106;&#105;&#101;&#64;&#50;&#54;&#51;&#46;&#110;&#101;&#116;">log4j.appender.A5.To=chunjie@263.net</a> </div>
<div><a target="_blank" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#65;&#53;&#46;&#70;&#114;&#111;&#109;&#61;&#101;&#114;&#114;&#111;&#114;&#64;&#101;&#114;&#114;&#111;&#114;&#46;&#99;&#111;&#109;">log4j.appender.A5.From=error@error.com</a> </div>
<div>log4j.appender.A5.Subject=ErrorLog </div>
<div>log4j.appender.A5.SMTPHost=smtp.263.net </div>
<div>log4j.appender.A5.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.A5.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n </div>
<div>3.调用代码： </div>
<div>//把日志发送到mail </div>
<div>Logger logger3 = Logger.getLogger("MailLog"); </div>
<div>logger3.warn("warn!!!"); </div>
<div>logger3.error("error!!!"); </div>
<div>logger3.fatal("fatal!!!"); </div>
<div>在后台输出所有类别的错误： </div>
<div>1. 写配置文件 </div>
<div># 在后台输出 </div>
<div>log4j.logger.c, A1 </div>
<div># APPENDER A1 </div>
<div>log4j.appender.A1=org.apache.log4j.ConsoleAppender </div>
<div>log4j.appender.A1.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n </div>
<div>2．调用代码 </div>
<div>Logger logger1 = Logger.getLogger("console"); </div>
<div>logger1.debug("debug!!!"); </div>
<div>logger1.info("info!!!"); </div>
<div>logger1.warn("warn!!!"); </div>
<div>logger1.error("error!!!"); </div>
<div>logger1.fatal("fatal!!!"); </div>
<div>-------------------------------------------------------------------- </div>
<div>全部配置文件：log4j.properties </div>
<div># 在后台输出 </div>
<div>log4j.logger.c, A1 </div>
<div># APPENDER A1 </div>
<div>log4j.appender.A1=org.apache.log4j.ConsoleAppender </div>
<div>log4j.appender.A1.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n </div>
<div># 在2000系统日志输出 </div>
<div>log4j.logger.NTlog=FATAL, A8 </div>
<div># APPENDER A8 </div>
<div>log4j.appender.A8=org.apache.log4j.nt.NTEventLogAppender </div>
<div>log4j.appender.A8.Source=JavaTest </div>
<div>log4j.appender.A8.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.A8.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n </div>
<div># 将日志发送到email </div>
<div>log4j.logger.MailLog=WARN,A5 </div>
<div>#&nbsp;&nbsp;APPENDER A5 </div>
<div>log4j.appender.A5=org.apache.log4j.net.SMTPAppender </div>
<div>log4j.appender.A5.BufferSize=5 </div>
<div><a target="_blank" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#65;&#53;&#46;&#84;&#111;&#61;&#99;&#104;&#117;&#110;&#106;&#105;&#101;&#64;&#50;&#54;&#51;&#46;&#110;&#101;&#116;">log4j.appender.A5.To=chunjie@263.net</a> </div>
<div><a target="_blank" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#111;&#103;&#52;&#106;&#46;&#97;&#112;&#112;&#101;&#110;&#100;&#101;&#114;&#46;&#65;&#53;&#46;&#70;&#114;&#111;&#109;&#61;&#101;&#114;&#114;&#111;&#114;&#64;&#101;&#114;&#114;&#111;&#114;&#46;&#99;&#111;&#109;">log4j.appender.A5.From=error@error.com</a> </div>
<div>log4j.appender.A5.Subject=ErrorLog </div>
<div>log4j.appender.A5.SMTPHost=smtp.263.net </div>
<div>log4j.appender.A5.layout=org.apache.log4j.PatternLayout </div>
<div>log4j.appender.A5.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n </div>
<div>全部代码：Log4jTest.java </div>
<div>&nbsp;&nbsp; </div>
<div>/* </div>
<div>&nbsp;&nbsp;* 创建日期 2003-11-13 </div>
<div>&nbsp;&nbsp;*/ </div>
<div>package edu.bcu.Bean; </div>
<div>import org.apache.log4j.*; </div>
<div>//import org.apache.log4j.nt.*; </div>
<div>//import org.apache.log4j.net.*; </div>
<div>/** </div>
<div>&nbsp;&nbsp;* @author yanxu </div>
<div>&nbsp;&nbsp;*/ </div>
<div>public class Log4jTest </div>
<div>{ </div>
<div>&nbsp;&nbsp;public static void main(String args[]) </div>
<div>&nbsp;&nbsp;{ </div>
<div>&nbsp;&nbsp; PropertyConfigurator.configure("log4j.properties"); </div>
<div>&nbsp;&nbsp; //在后台输出 </div>
<div>&nbsp;&nbsp; Logger logger1 = Logger.getLogger("console"); </div>
<div>&nbsp;&nbsp; logger1.debug("debug!!!"); </div>
<div>&nbsp;&nbsp; logger1.info("info!!!"); </div>
<div>&nbsp;&nbsp; logger1.warn("warn!!!"); </div>
<div>&nbsp;&nbsp; logger1.error("error!!!"); </div>
<div>&nbsp;&nbsp; logger1.fatal("fatal!!!"); </div>
<div>&nbsp;&nbsp; //在NT系统日志输出 </div>
<div>&nbsp;&nbsp; Logger logger2 = Logger.getLogger("NTlog"); </div>
<div>&nbsp;&nbsp; //NTEventLogAppender nla = new NTEventLogAppender(); </div>
<div>&nbsp;&nbsp; logger2.debug("debug!!!"); </div>
<div>&nbsp;&nbsp; logger2.info("info!!!"); </div>
<div>&nbsp;&nbsp; logger2.warn("warn!!!"); </div>
<div>&nbsp;&nbsp; logger2.error("error!!!"); </div>
<div>&nbsp;&nbsp; //只有这个错误才会写入2000日志 </div>
<div>&nbsp;&nbsp; logger2.fatal("fatal!!!"); </div>
<div>&nbsp;&nbsp; //把日志发送到mail </div>
<div>&nbsp;&nbsp; Logger logger3 = Logger.getLogger("MailLog"); </div>
<div>&nbsp;&nbsp; //SMTPAppender sa = new SMTPAppender(); </div>
<div>&nbsp;&nbsp; logger3.warn("warn!!!"); </div>
<div>&nbsp;&nbsp; logger3.error("error!!!"); </div>
<div>&nbsp;&nbsp; logger3.fatal("fatal!!!"); </div>
<div>&nbsp;&nbsp;} </div>
<div>} </div>
&nbsp;
<img src ="http://www.blogjava.net/java-blog/aggbug/180369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-02-17 23:51 <a href="http://www.blogjava.net/java-blog/articles/180369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK5 线程池2</title><link>http://www.blogjava.net/java-blog/articles/176225.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Fri, 18 Jan 2008 07:18:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/176225.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/176225.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/176225.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/176225.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/176225.html</trackback:ping><description><![CDATA[&nbsp;昨天开始研究java的多线程包java.util.concurrent，根据自己的理解实现了一个消息队列异步调用(200行代码左右)。拿出来与大家分享我的劳动成果。<br />
&nbsp;&nbsp;希望大家多提意见。指出哪里写的不好，以后加以改正。<br />
<br />
ThreadPoolManager类：负责管理线程池，调用轮询的线程来访问字符串缓冲区的内容，维护缓冲区，当线程池溢出时抛出的Runnable任务被加入到字符缓冲区。<br />
public&nbsp;class&nbsp;ThreadPoolManager<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;ThreadPoolManager&nbsp;tpm&nbsp;=&nbsp;new&nbsp;ThreadPoolManager();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;线程池维护线程的最少数量<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;static&nbsp;int&nbsp;CORE_POOL_SIZE&nbsp;=&nbsp;4;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;线程池维护线程的最大数量<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;static&nbsp;int&nbsp;MAX_POOL_SIZE&nbsp;=&nbsp;10;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;线程池维护线程所允许的空闲时间<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;static&nbsp;int&nbsp;KEEP_ALIVE_TIME&nbsp;=&nbsp;0;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;线程池所使用的缓冲队列大小<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;static&nbsp;int&nbsp;WORK_QUEUE_SIZE&nbsp;=&nbsp;10;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;消息缓冲队列<br />
&nbsp;&nbsp;&nbsp;&nbsp;Queue&lt;String&gt;&nbsp;msgQueue&nbsp;=&nbsp;new&nbsp;LinkedList&lt;String&gt;();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;访问消息缓存的调度线程<br />
&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;Runnable&nbsp;accessBufferThread&nbsp;=&nbsp;new&nbsp;Runnable()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;查看是否有待定请求，如果有，则创建一个新的AccessDBThread，并添加到线程池中<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;hasMoreAcquire()&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;msg&nbsp;=&nbsp;(&nbsp;String&nbsp;)&nbsp;msgQueue.poll();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runnable&nbsp;task&nbsp;=&nbsp;new&nbsp;AccessDBThread(&nbsp;msg&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadPool.execute(&nbsp;task&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;};<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;RejectedExecutionHandler&nbsp;handler&nbsp;=&nbsp;new&nbsp;RejectedExecutionHandler()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;rejectedExecution(&nbsp;Runnable&nbsp;r,&nbsp;ThreadPoolExecutor&nbsp;executor&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(((AccessDBThread&nbsp;)r).getMsg()+"消息放入队列中重新等待执行");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msgQueue.offer(((&nbsp;AccessDBThread&nbsp;)&nbsp;r&nbsp;).getMsg()&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;};<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;管理数据库访问的线程池<br />
&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;ThreadPoolExecutor&nbsp;threadPool&nbsp;=&nbsp;new&nbsp;ThreadPoolExecutor(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CORE_POOL_SIZE,&nbsp;MAX_POOL_SIZE,&nbsp;KEEP_ALIVE_TIME,&nbsp;TimeUnit.SECONDS,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;ArrayBlockingQueue(&nbsp;WORK_QUEUE_SIZE&nbsp;),&nbsp;this.handler&nbsp;);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;调度线程池<br />
&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;ScheduledExecutorService&nbsp;scheduler&nbsp;=&nbsp;Executors<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.newScheduledThreadPool(&nbsp;1&nbsp;);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;ScheduledFuture&nbsp;taskHandler&nbsp;=&nbsp;scheduler.scheduleAtFixedRate(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;accessBufferThread,&nbsp;0,&nbsp;1,&nbsp;TimeUnit.SECONDS&nbsp;);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;ThreadPoolManager&nbsp;newInstance()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;tpm;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;ThreadPoolManager(){}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;boolean&nbsp;hasMoreAcquire()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;!msgQueue.isEmpty();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;addLogMsg(&nbsp;String&nbsp;msg&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runnable&nbsp;task&nbsp;=&nbsp;new&nbsp;AccessDBThread(&nbsp;msg&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadPool.execute(&nbsp;task&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
<br />
public&nbsp;class&nbsp;AccessDBThread&nbsp;implements&nbsp;Runnable<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;msg;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;getMsg()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;msg;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setMsg(&nbsp;String&nbsp;msg&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.msg&nbsp;=&nbsp;msg;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;AccessDBThread(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;AccessDBThread(String&nbsp;msg){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.msg&nbsp;=&nbsp;msg;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;向数据库中添加Msg变量值<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Added&nbsp;the&nbsp;message:&nbsp;"+msg+"&nbsp;into&nbsp;the&nbsp;Database");<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}<br />
<br />
public&nbsp;class&nbsp;TestDriver<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;ThreadPoolManager&nbsp;tpm&nbsp;=&nbsp;ThreadPoolManager.newInstance();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;sendMsg(&nbsp;String&nbsp;msg&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tpm.addLogMsg(&nbsp;msg&nbsp;+&nbsp;"记录一条日志&nbsp;"&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(&nbsp;String[]&nbsp;args&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(&nbsp;int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;100;&nbsp;i++&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;TestDriver().sendMsg(&nbsp;Integer.toString(&nbsp;i&nbsp;)&nbsp;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}
<img src ="http://www.blogjava.net/java-blog/aggbug/176225.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-01-18 15:18 <a href="http://www.blogjava.net/java-blog/articles/176225.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK5 线程池</title><link>http://www.blogjava.net/java-blog/articles/176222.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Fri, 18 Jan 2008 07:16:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/176222.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/176222.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/176222.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/176222.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/176222.html</trackback:ping><description><![CDATA[Java5增加了新的类库并发集java.util.concurrent，该类库为并发程序提供了丰富的API多线程编程在Java
5中更加容易，灵活。本文通过一个网络服务器模型，来实践Java5的多线程编程，该模型中使用了Java5中的线程池，阻塞队列，可重入锁等，还实践了
Callable， Future等接口，并使用了Java 5的另外一个新特性泛型。<br />
<br />
简介 <br />
<br />
本文将实现一个网络服务器模型，一旦有客户端连接到该服务器，则启动一个新线程为该连接服务，服务内容为往客户端输送一些字符信息。一个典型的网络服务器模型如下：<br />
<br />
1. 建立监听端口。<br />
<br />
2. 发现有新连接，接受连接，启动线程，执行服务线程。 3. 服务完毕，关闭线程。<br />
<br />
这个模型在大部分情况下运行良好，但是需要频繁的处理用户请求而每次请求需要的服务又是简短的时候，系统会将大量的时间花费在线程的创建销毁。Java
5的线程池克服了这些缺点。通过对重用线程来执行多个任务，避免了频繁线程的创建与销毁开销，使得服务器的性能方面得到很大提高。因此，本文的网络服务器
模型将如下：<br />
<br />
1. 建立监听端口，创建线程池。<br />
<br />
2. 发现有新连接，使用线程池来执行服务任务。<br />
<br />
3. 服务完毕，释放线程到线程池。<br />
<br />
下面详细介绍如何使用Java 5的concurrent包提供的API来实现该服务器。<br />
<br />
初始化<br />
<br />
初始化包括创建线程池以及初始化监听端口。创建线程池可以通过调用java.util.concurrent.Executors类里的静态方法
newChahedThreadPool或是newFixedThreadPool来创建，也可以通过新建一个
java.util.concurrent.ThreadPoolExecutor实例来执行任务。这里我们采用newFixedThreadPool方
法来建立线程池。<br />
<br />
ExecutorService pool = Executors.newFixedThreadPool(10); <br />
<br />
表示新建了一个线程池，线程池里面有10个线程为任务队列服务。<br />
<br />
使用ServerSocket对象来初始化监听端口。<br />
<br />
private static final int PORT = 19527;<br />
serverListenSocket = new ServerSocket(PORT);<br />
serverListenSocket.setReuseAddress(true);<br />
serverListenSocket.setReuseAddress(true); <br />
<br />
服务新连接<br />
<br />
当有新连接建立时，accept返回时，将服务任务提交给线程池执行。<br />
<br />
while(true){<br />
Socket socket = serverListenSocket.accept();<br />
pool.execute(new ServiceThread(socket));<br />
} <br />
<br />
这里使用线程池对象来执行线程，减少了每次线程创建和销毁的开销。任务执行完毕，线程释放到线程池。<br />
<br />
服务任务<br />
<br />
服务线程ServiceThread维护一个count来记录服务线程被调用的次数。每当服务任务被调用一次时，count的值自增1，因此
ServiceThread提供一个increaseCount和getCount的方法，分别将count值自增1和取得该count值。由于可能多个
线程存在竞争，同时访问count，因此需要加锁机制，在Java 5之前，我们只能使用synchronized来锁定。Java
5中引入了性能更加粒度更细的重入锁ReentrantLock。我们使用ReentrantLock保证代码线程安全。下面是具体代码：<br />
<br />
private static ReentrantLock lock = new ReentrantLock ();<br />
private static int count = 0;<br />
private int getCount(){<br />
int ret = 0;<br />
try{<br />
lock.lock();<br />
ret = count;<br />
}finally{<br />
lock.unlock();<br />
}<br />
return ret;<br />
} <br />
private void increaseCount(){<br />
try{<br />
lock.lock();<br />
++count;<br />
}finally{<br />
lock.unlock();<br />
}<br />
} <br />
<br />
服务线程在开始给客户端打印一个欢迎信息，<br />
<br />
increaseCount();<br />
int curCount = getCount();<br />
helloString = "hello, id = " + curCount+""r"n";<br />
dos = new DataOutputStream(connectedSocket.getOutputStream());<br />
dos.write(helloString.getBytes()); <br />
<br />
然后使用ExecutorService的submit方法提交一个Callable的任务，返回一个Future接口的引用。这种做法对费时的任务非
常有效，submit任务之后可以继续执行下面的代码，然后在适当的位置可以使用Future的get方法来获取结果，如果这时候该方法已经执行完毕，则
无需等待即可获得结果，如果还在执行，则等待到运行完毕。<br />
<br />
ExecutorService executor = Executors.newSingleThreadExecutor();<br />
Future future = executor.submit(new TimeConsumingTask());<br />
dos.write("let's do soemthing other".getBytes());<br />
String result = future.get();<br />
dos.write(result.getBytes()); <br />
<br />
其中TimeConsumingTask实现了Callable接口<br />
<br />
class TimeConsumingTask implements Callable {<br />
public String call() throws Exception {<br />
System.out.println("It's a time-consuming task, you'd better retrieve your result in the furture");<br />
return "ok, here's the result: It takes me lots of time to produce this result";<br />
}<br />
} <br />
<br />
这里使用了Java
5的另外一个新特性泛型，声明TimeConsumingTask的时候使用了String做为类型参数。必须实现Callable接口的call函数，
其作用类似与Runnable中的run函数，在call函数里写入要执行的代码，其返回值类型等同于在类声明中传入的类型值。在这段程序中，我们提交了
一个Callable的任务，然后程序不会堵塞，而是继续执行dos.write("let's do soemthing
other".getBytes());当程序执行到String result =
future.get()时如果call函数已经执行完毕，则取得返回值，如果还在执行，则等待其执行完毕。
<img src ="http://www.blogjava.net/java-blog/aggbug/176222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-01-18 15:16 <a href="http://www.blogjava.net/java-blog/articles/176222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：一个bit操作的类   </title><link>http://www.blogjava.net/java-blog/articles/169119.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Thu, 20 Dec 2007 10:18:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/169119.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/169119.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/169119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/169119.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/169119.html</trackback:ping><description><![CDATA[因为工作需要，需要操纵和读写一个Java的byte中每一位的值，所以昨天写了这么一个类。
<p>&nbsp;&nbsp;&nbsp;&nbsp;不知道有没有更好的方法，拿出来让大家看看吧！</p>
<p>源代码：</p>
<p>/**<br />
&nbsp;* @author 沈东良 Edward Shen&lt;a href="<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#104;&#101;&#110;&#100;&#108;&#95;&#115;&#64;&#104;&#111;&#116;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;&#37;&#50;&#50;&#37;&#51;&#69;&#115;&#104;&#101;&#110;&#100;&#108;&#95;&#115;&#64;&#104;&#111;&#116;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;&#37;&#51;&#67;&#47;&#97;">mailto:shendl_s@hotmail.com"&gt;shendl_s@hotmail.com&lt;/a</a>&gt;<br />
&nbsp;* 2007-5-23 下午03:11:45<br />
&nbsp;*执行位操作<br />
&nbsp;*<br />
&nbsp;*<br />
&nbsp;*/<br />
public class BitUtil {<br />
&nbsp;/**<br />
&nbsp; * 把字节指定的位数设为1，不管原来该位是什么。<br />
&nbsp; * @param data<br />
&nbsp; * @param pos&nbsp; 从0开始<br />
&nbsp; */<br />
&nbsp;public static byte setByteBitOne(byte data,int pos){<br />
&nbsp;&nbsp;byte compare=(byte) Math.pow(2.0,pos);<br />
&nbsp;&nbsp;data=(byte) (data|compare);<br />
&nbsp;&nbsp;return data;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 把字节指定的位数设为0，不管原来该位是什么。<br />
&nbsp; * @param data<br />
&nbsp; * @param pos<br />
&nbsp; */<br />
&nbsp;public static byte setByteBitZero(byte data,int pos){<br />
&nbsp;&nbsp;byte compare=(byte) ~(byte) Math.pow(2.0,pos);<br />
&nbsp;&nbsp;data=(byte) (data&amp;compare);<br />
&nbsp;&nbsp;return data;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 返回指定字节第几个位的数字，只可能是０或者１<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param data<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param pos&nbsp;&nbsp; 从0开始的位数<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @return<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;public static int getByteBit(byte data,int pos){<br />
&nbsp;&nbsp;int bitData = 0;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;byte compare=(byte) Math.pow(2.0,pos);<br />
&nbsp;&nbsp;if((data &amp; compare)==compare){<br />
&nbsp;&nbsp;&nbsp;bitData =1;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;return bitData;<br />
&nbsp;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 返回一个字节的每一位的数字<br />
&nbsp; * @param data<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;public static byte[] getByteBits(byte data){<br />
&nbsp;&nbsp;byte[] results=new byte[8];<br />
&nbsp;&nbsp;for(int i=0;i&lt;8;i++){<br />
&nbsp;&nbsp;&nbsp;results[i]=(byte) BitUtil.getByteBit(data, i);<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;return results;<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * <br />
&nbsp; */<br />
&nbsp;public BitUtil() {<br />
&nbsp;&nbsp;/*<br />
&nbsp;&nbsp; *<br />
&nbsp;&nbsp; */<br />
&nbsp;}</p>
<p>&nbsp;}<br />
&nbsp;</p>
<img src ="http://www.blogjava.net/java-blog/aggbug/169119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2007-12-20 18:18 <a href="http://www.blogjava.net/java-blog/articles/169119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用临时变量提高Java代码性能 (转)</title><link>http://www.blogjava.net/java-blog/articles/158871.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Wed, 07 Nov 2007 09:18:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/158871.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/158871.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/158871.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/158871.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/158871.html</trackback:ping><description><![CDATA[<div style="margin: 0cm 0cm 0pt;"><font size="2">author: ZJ 2007-11-6</font></div>
<div style="margin: 0cm 0cm 0pt;"><font size="2">Blog: </font><font color="#800080" size="2"><a href="http://zhangjunhd.blog.51cto.com/" target="_blank">http://zhangjunhd.blog.51cto.com/</a></font></div>
<div style="margin: 0cm 0cm 0pt;">&nbsp;</div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman=""><font size="2">一个Java类中可以存在多种形式的变量，可以是最一般的成员变量；或将其定义为静态变量；也可以在方法中定义临时变量。这三种变量的存取效率如何？</font></span></div>
<div style="margin: 0cm 0cm 0pt;"><font size="2"><strong><span style="font-size: 14pt;">1</span></strong><strong><span style="font-size: 14pt; font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">．测试</span></strong></font></div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman=""><font size="2">下面作个实验，看下面代码。</font></span></div>
<table style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="padding: 0cm 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 426.1pt;" valign="top" width="568">
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">class</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> CheckVars {</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">private</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">instVar</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">;</span><span style="font-size: 10pt; color: #3f7f5f;" courier=""  new?;="" 0pt="">// </span><span style="font-size: 10pt; color: #3f7f5f; font-family: 宋体;" courier=""  new?;="" ? courier="" new="">成员变量</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">private</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">static</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">staticVar</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">; </span><span style="font-size: 10pt; color: #3f7f5f;" courier=""  new?;="" 0pt="">// </span><span style="font-size: 10pt; color: #3f7f5f; font-family: 宋体;" courier=""  new?;="" ? courier="" new="">静态变量</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left">&nbsp;</div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #3f7f5f;" courier=""  new?;="" 0pt="">// </span><span style="font-size: 10pt; color: #3f7f5f; font-family: 宋体;" courier=""  new?;="" ? courier="" new="">存取类方法中的临时变量</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">void</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> tempAccess(</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> val) {</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> j = 0;</span><span style="font-size: 10pt; color: #3f7f5f;" courier=""  new?;="" 0pt="">// </span><span style="font-size: 10pt; color: #3f7f5f; font-family: 宋体;" courier=""  new?;="" ? courier="" new="">临时变量</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> startTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">for</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> (</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> i = 0; i &lt; val; i++)</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; j += 1;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> endTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.</span><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">out</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">.println(</span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">"temp var: "</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> + (endTime - startTime) + </span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">" milli seconds"</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; }</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left">&nbsp;</div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #3f7f5f;" courier=""  new?;="" 0pt="">// </span><span style="font-size: 10pt; color: #3f7f5f; font-family: 宋体;" courier=""  new?;="" ? courier="" new="">存取类的成员变量</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">void</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> instanceAccess(</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> val) {</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> startTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">for</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> (</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> i = 0; i &lt; val; i++)</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">instVar</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> += 1;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> endTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.</span><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">out</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">.println(</span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">"instance var: "</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> + (endTime - startTime) + </span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">" milli seconds"</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; }</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left">&nbsp;</div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #3f7f5f;" courier=""  new?;="" 0pt="">// </span><span style="font-size: 10pt; color: #3f7f5f; font-family: 宋体;" courier=""  new?;="" ? courier="" new="">存取类的</span><span style="font-size: 10pt; color: #3f7f5f;" courier=""  new?;="" 0pt=""> static </span><span style="font-size: 10pt; color: #3f7f5f; font-family: 宋体;" courier=""  new?;="" ? courier="" new="">变量</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">void</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> staticAccess(</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> val) {</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> startTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">for</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> (</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> i = 0; i &lt; val; i++)</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">staticVar</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> += 1;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> endTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.</span><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">out</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">.println(</span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">"static var: "</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> + (endTime - startTime) + </span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">" milli seconds"</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; }</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">public</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">static</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">void</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> main(String[] args){</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CheckVars test=</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">new</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> CheckVars();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test.tempAccess(200000000);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test.instanceAccess(200000000);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test.staticAccess(200000000);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; }</span></div>
            <div style="margin: 0cm 0cm 0pt;"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">}</span></div>
            </td>
        </tr>
    </tbody>
</table>
<div style="margin: 0cm 0cm 0pt;">&nbsp;</div>
<div style="margin: 0cm 0cm 0pt;"><font size="2"><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">结果：</span></font></div>
<div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt;="" fr="">temp var: 350 milli seconds</span></div>
<div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">instance</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt;="" fr=""> var: 821 milli seconds</span></div>
<div style="margin: 0cm 0cm 0pt;"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt;="" fr="">static var: 852 milli seconds</span></div>
<div style="margin: 0cm 0cm 0pt;">&nbsp;</div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="2"><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">这段代码中的每个方法都执行相同的循环</span><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" fr="">，</span><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">并反复相同的次数。唯一的不同是每个循环使一个不同类型的变量递增。方法</span> tempAccess <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">使一个局部堆栈变量递增，</span>instanceAccess <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">使类的一个成员实例变量递增，而</span> staticAccess <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">使类的一个</span> static <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">变量递增。</span></font></div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21.1pt;"><font size="2"><strong><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">从结果中可以发现，</span>instanceAccess </strong><strong><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">和</span> staticAccess </strong><strong><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">的执行时间基本相同。但是，</span>tempAccess </strong><strong><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">要快两到三倍。</span></strong></font></div>
<div style="margin: 0cm 0cm 0pt;">&nbsp;</div>
<div style="margin: 0cm 0cm 0pt;"><font size="2"><strong><span style="font-size: 14pt;">2</span></strong><strong><span style="font-size: 14pt; font-family: 宋体;" times=""  roman?;="" ? times="" new="" fr="">．</span></strong><strong><span style="font-size: 14pt;">JVM</span></strong><strong><span style="font-size: 14pt; font-family: 宋体;" times=""  roman?;="" ? times="" new="" fr="">存取变量机制</span></strong></font></div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="2"><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">存取堆栈变量如此快是因为</span>JVM <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">存取堆栈变量比它存取</span> static <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">变量或类的实例变量执行的操作少。</span></font></div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="2">JVM <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">是一种基于堆栈的虚拟机，因此优化了对堆栈数据的存取和处理。所有局部变量都存储在一个局部变量表中，在</span> Java <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">操作数堆栈中进行处理，并可被高效地存取。</span></font></div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="2"><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">存取</span> static <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">变量和实例变量成本更高，因为</span> JVM <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">必须使用代价更高的操作码，并从常数存储池中存取它们。（常数存储池保存一个类型所使用的所有类型、字段和方法的符号引用。）通常，在第一次从常数存储池中访问</span> static <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">变量或实例变量以后，</span>JVM <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">将动态更改字节码以使用效率更高的操作码。尽管有这种优化，堆栈变量的存取仍然更快。</span></font></div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21pt;">&nbsp;</div>
<div style="margin: 0cm 0cm 0pt;"><font size="2"><strong><span style="font-size: 14pt;">3</span></strong><strong><span style="font-size: 14pt; font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">．优化代码</span></strong></font></div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="2"><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">考虑到这些事实，就可以重新构建前面的代码，以便通过存取堆栈变量而不是实例变量或</span> static <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">变量使操作更高效。</span></font></div>
<table style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="padding: 0cm 5.4pt; background: #e6e6e6 none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; width: 426.1pt;" valign="top" width="568">
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">public</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">class</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> CheckVarsAdv {</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">private</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">instVar</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">private</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">static</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">staticVar</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">; </span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left">&nbsp;</div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">void</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> tempAccess(</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> val) {</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> j = 0;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> startTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">for</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> (</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> i = 0; i &lt; val; i++)</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; j += 1;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> endTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.</span><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">out</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">.println(</span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">"temp var: "</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> + (endTime - startTime) + </span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">" milli seconds"</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; }</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left">&nbsp;</div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">void</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> instanceAccess(</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> val) {</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> j = </span><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">instVar</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> startTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">for</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> (</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> i = 0; i &lt; val; i++)</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; j += 1;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> endTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.</span><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">out</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">.println(</span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">"instance var: "</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> + (endTime - startTime) + </span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">" milli seconds"</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">instVar</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> = j;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; }</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left">&nbsp;</div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">void</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> staticAccess(</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> val) {</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> j = </span><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">staticVar</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> startTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">for</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> (</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">int</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> i = 0; i &lt; val; i++)</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; j += 1;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">long</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> endTime = System.<em>currentTimeMillis</em>();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.</span><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">out</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">.println(</span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">"static var: "</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> + (endTime - startTime) + </span><span style="font-size: 10pt; color: #2a00ff;" courier=""  new?;="" 0pt="">" milli seconds"</span><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><em><span style="font-size: 10pt; color: #0000c0;" courier=""  new?;="" 0pt="">staticVar</span></em><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> = j;</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; }</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">public</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">static</span></strong><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">void</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> main(String[] args){</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CheckVarsAdv test=</span><strong><span style="font-size: 10pt; color: #7f0055;" courier=""  new?;="" 0pt="">new</span></strong><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt=""> CheckVarsAdv();</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test.tempAccess(200000000);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test.instanceAccess(200000000);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test.staticAccess(200000000);</span></div>
            <div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">&nbsp;&nbsp;&nbsp; }</span></div>
            <div style="margin: 0cm 0cm 0pt;"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">}</span></div>
            </td>
        </tr>
    </tbody>
</table>
<div style="margin: 0cm 0cm 0pt;">&nbsp;</div>
<div style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman=""><font size="2">结果：</font></span></div>
<div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">temp var: 341 milli seconds</span></div>
<div style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">instance var: 370 milli seconds</span></div>
<div style="margin: 0cm 0cm 0pt;"><span style="font-size: 10pt; color: black;" courier=""  new?;="" 0pt="">static var: 361 milli seconds</span></div>
<div style="margin: 0cm 0cm 0pt;">&nbsp;</div>
<div style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font size="2"><span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">方法</span> instanceAccess <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">和</span> staticAccess <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">被修改为将它们的实例变量或</span> static <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">变量复制到局部堆栈变量中。当变量的处理完成以后，其值又被复制回实例变量或</span> static <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">变量中。这种简单的更改明显提高了</span> instanceAccess <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">和</span> staticAccess <span style="font-family: 宋体;" times=""  roman?;="" ? times="" new="" roman="">的性能。这三个方法的执行时间现在基本相同。</span></font></div>
<p>本文出自 &#8220;<a href="http://zhangjunhd.blog.51cto.com/">子 孑</a>&#8221; 博客，请务必保留此出处<a href="http://zhangjunhd.blog.51cto.com/113473/49322">http://zhangjunhd.blog.51cto.com/113473/49322</a></p>
<img src ="http://www.blogjava.net/java-blog/aggbug/158871.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2007-11-07 17:18 <a href="http://www.blogjava.net/java-blog/articles/158871.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编写跨平台Java程序的几个要点</title><link>http://www.blogjava.net/java-blog/articles/156698.html</link><dc:creator>一步一步努力向上爬</dc:creator><author>一步一步努力向上爬</author><pubDate>Mon, 29 Oct 2007 07:49:00 GMT</pubDate><guid>http://www.blogjava.net/java-blog/articles/156698.html</guid><wfw:comment>http://www.blogjava.net/java-blog/comments/156698.html</wfw:comment><comments>http://www.blogjava.net/java-blog/articles/156698.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/java-blog/comments/commentRss/156698.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/java-blog/services/trackbacks/156698.html</trackback:ping><description><![CDATA[<h2><a href="http://www.b9527.net/?q=node/12">编写跨平台Java程序的几个要点</a></h2>
Submitted by <a href="http://www.b9527.net/?q=user/1" title="查看用户信息。">robertb9527</a> on 八月 8, 2004 - 12:50.
<ul inline="">
    <li last="" taxonomy_term_1=""><a href="http://www.b9527.net/?q=taxonomy/term/1" rel="tag" title="老康的Program" class="taxonomy_term_1">Program</a></li>
</ul>
<div>
<p>用Java编写程序最大的优点在于&#8220;一次编译，处处运行&#8221;，可是事实上，相当一部分的Java程序不能在别的操作系统上正确运行，最后倒搞成了&#8220;一次编写，处处调试&#8221;，那么如何才能编写一个真正的跨平台的Java程序呢？下面有几个要点要注意： </p>
<p>　　1.你的程序需要是100%纯Java的。特别是使用第三方的类库包时一定要注意这一点。 </p>
<p>　　2.无论你使用的是JDK或其他开发工具，在编译时都要打开所有的警告选项，这样编译器可以尽可能多的发现平台相关的语句，并给出警告。虽然不能保证没有编译时警告的程序一定是跨平台的，但含有警告的程序却很有可能是非平台无关的。 </p>
<p>　　3.由于JDK是向下兼容的，因此可以使用过时的方法（Deprecated method），但调试时要打开－deprecation选项。</p>
<p>
4.退出Java程序时尽量不要使用java.lang.System的exit方法。Exit
方法可以终止JVM，从而终止程序，但如果同时运行了另一个Java程序，使用exit方法就会让该程序也关闭，这显然不是我们希望看到的情况。事实上要
退出Java程序，可以使用destory()退出一个独立运行的线程。对于多线程程序，必须要关闭各个非守护线程。只有在程序非正常退出时，才使用
exit方法退出程序。 </p>
<p>　　5.避免使用本地方法和本地代码，尽可能自己编写具有相应功能的Java类，改写该方法。如果一定要使用该本地方法，可以编写一个服务器程序调用该方法，然后将现在要编写的程序作为该服务器程序的客户程序，或者考虑CORBA（公共对象请求代理）程序结构。 </p>
<p>
6.Java中有一个类似于Delphi中的winexec的方法，java.lang.runtime类的exec方法，作为该方法本身是具有平台无
关性的，但是给方法所调用的命令及命令参数却是与平台相关的，因此，在编写程序时要避免使用，如果一定要调用其他的程序的话，必须要让用户自己来设置该命
令及其参数。比如说，在windows中可以调用notepad.exe程序，在linux 中就要调用vi程序了。 </p>
<p>　　7.注意并不是所有的操作系统都支持Unicode字符集，这对于跨平台的Java中文软件程序不能不说是一大噩耗。 </p>
<p>
8.在程序中不要硬性编码与平台相关的任何常量，比如行分隔符，文件分隔符，路径分隔符等等，这些常量在不同的平台上是不同的，比如文件分隔符，在
UNIX和MAC中是&#8220;/&#8221;，在windows中是&#8220;"&#8221;，如果要使用这些常量，需要使用jdava.util.Properties类的
getProperty方法，如java.util.Properties.getProperty(&#8220;file.separator&#8221;)可以获得文件分
隔符，getProperty
(&#8220;line.separator&#8221;)返回行分隔符，getProperty(&#8220;path.separator&#8221;)返回路径分隔符。 </p>
<p>
9.在编写跨平台的网络程序时，不要使用java.net.InetAddress类的getHostName方法得到主机名，因为不同的平台的主机名
格式是不同的，最好使用getAddress得到格式相同的IP地址，另外，程序中所有的主机名都要换成IP地址，比如www.b9527.net就要换
成相应的IP地址。 </p>
<p>　　10.涉及文件操作的程序需要注意：不要在程序中硬性编码文件路径，而且不同平台对于文件名使用的字符及最大文件名长度的要求不同，编写你的程序的时候要使用一般的ASCII码字符作为文件的名字，而且不能与平台中已存在的程序同名，否则会造成冲突。 </p>
<p>　　11.如果你写的程序是GUI程序，在使用AWT组件时不要硬性设置组件的大小和位置而应该使用Java的布局管理器来设置和管理可视组件的大小和位置，否则有可能造成布局混乱。 </p>
<p>
12.由于不同的操作系统，不同的机器，系统支持的颜色和屏幕的大小和分辨率都不同，如何获得这些属性呢？使用
java.awt.Systemcolor类可以获得需要的颜色，如该类的inactiveCaption
就是窗口边框中活动标题的背景颜色，menu则是菜单的背景颜色。使用java.awt.Toolkit的getScreenResolution可以以
&#8220;像素每英寸&#8221;为单位显示屏幕的分辨率。该类的getScreenSize可以得到屏幕大小(英寸)，loadSystemColors可以列出所有的系
统颜色。</p>
</div>
<img src ="http://www.blogjava.net/java-blog/aggbug/156698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/java-blog/" target="_blank">一步一步努力向上爬</a> 2007-10-29 15:49 <a href="http://www.blogjava.net/java-blog/articles/156698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>