??xml version="1.0" encoding="utf-8" standalone="yes"?>在线观看亚洲成人,亚洲人成人77777网站,亚洲成人福利在线http://www.tkk7.com/java-blog/category/26735.htmlzh-cnFri, 18 Apr 2008 13:53:51 GMTFri, 18 Apr 2008 13:53:51 GMT60java.util.concurrent 多线E框?/title><link>http://www.tkk7.com/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.tkk7.com/java-blog/articles/193845.html</guid><wfw:comment>http://www.tkk7.com/java-blog/comments/193845.html</wfw:comment><comments>http://www.tkk7.com/java-blog/articles/193845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/java-blog/comments/commentRss/193845.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/java-blog/services/trackbacks/193845.html</trackback:ping><description><![CDATA[<br /> JDK5中的一个亮点就是将Doug Lea的ƈ发库引入到Java标准库中。Doug Lea实是一个牛人,能教书,能出书,能编码,不过q在国外q是比较普遍的,而国内的教授们就相差太远?jin)? <br /> <br /> 一般的服务器都需要线E池Q比如Web、FTP{服务器Q不q它们一般都自己实现?jin)线E池Q比如以前介l过的Tomcat、Resin和Jetty{,现在有了(jin)JDK5Q我们就没有必要重复造R轮了(jin)Q直接用就可以Q何况用也很方便,性能也非帔R? <br /> <br /> <div> <div> <div>Java代码 <a 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 concurrent;  </li> <li>import java.util.concurrent.ExecutorService;  </li> <li>import java.util.concurrent.Executors;  </li> <li>public class TestThreadPool {  </li> <li>public static void main(String args[]) throws InterruptedException {  </li> <li>// only two threads  </li> <li>ExecutorService exec = Executors.newFixedThreadPool(2);  </li> <li>for(int index = 0; index < 100; index++) {  </li> <li>Runnable run = new Runnable() {  </li> <li>public void run() {  </li> <li>long time = (long) (Math.random() * 1000);  </li> <li>System.out.println(“Sleeping ” + time + “ms”);  </li> <li>try {  </li> <li>Thread.sleep(time);  </li> <li>} catch (InterruptedException e) {  </li> <li>}  </li> <li>}  </li> <li>};  </li> <li>exec.execute(run);  </li> <li>}  </li> <li>// must shutdown  </li> <li>exec.shutdown();  </li> <li>}  </li> <li>}  </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 < 100; index++) { Runnable run = new Runnable() { public void run() { long time = (long) (Math.random() * 1000); System.out.println(“Sleeping ” + time + “ms”); try { Thread.sleep(time); } catch (InterruptedException e) { } } }; exec.execute(run); } // must shutdown exec.shutdown(); } } </pre> <br /> 上面是一个简单的例子Q用了(jin)2个大的U程池来处理100个线E。但有一个问题:(x)在for循环的过E中Q会(x){待U程池有I闲的线E,所以主U程 ?x)阻塞的。ؓ(f)?jin)解册个问题,一般启动一个线E来做for循环Q就是ؓ(f)?jin)避免由于线E池满了(jin)造成ȝE阻塞。不q在q里我没有这样处理。[重要修正Q经q? 试Q即使线E池大小于实际U程数大,U程池也不会(x)d的,q与Tomcat的线E池不同Q它?yu)Runnable实例攑ֈ一?#8220;无限”? BlockingQueue中,所以就不用一个线E启动for循环QDoug Lea果然厉害] <br /> <br /> 另外它用了(jin)Executors的静(rn)态函数生成一个固定的U程池,֐思义Q线E池的线E是不会(x)释放的,即它是Idle。这׃(x)产生性能问题Q? 比如如果U程池的大小?00Q当全部使用完毕后,所有的U程?x)l留在池中,相应的内存和U程切换Qwhile(true)+sleep循环Q都?x)? 加。如果要避免q个问题Q就必须直接使用ThreadPoolExecutor()来构造。可以像Tomcat的线E池一栯|?#8220;最大线E数”?#8220;最线 E数”?#8220;I闲U程keepAlive的时?#8221;。通过q些可以基本上替换Tomcat的线E池实现Ҏ(gu)? <br /> <br /> 需要注意的是线E池必须使用shutdown来显式关闭,否则ȝE就无法退出。shutdown也不?x)阻塞主U程? <br /> <br /> 许多长时间运行的应用有时候需要定时运行Q务完成一些诸如统计、优化等工作Q比如在?sh)信行业中处理用戯单时Q需要每?分钟处理话单Q网站每? 凌晨l计用户讉K量、用hQ大型超时凌?点统计当天销售额、以?qing)最热卖的商品;每周日进行数据库备䆾Q公司每个月?0可工资ƈq行转帐{,q些 都是定时d。通过 java的ƈ发库concurrent可以L的完成这些Q务,而且非常的简单? <br /> <br /> <div> <div> <div>Java代码 <a 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 concurrent;  </li> <li>import static java.util.concurrent.TimeUnit.SECONDS;  </li> <li>import java.util.Date;  </li> <li>import java.util.concurrent.Executors;  </li> <li>import java.util.concurrent.ScheduledExecutorService;  </li> <li>import java.util.concurrent.ScheduledFuture;  </li> <li>public class TestScheduledThread {  </li> <li>public static void main(String[] args) {  </li> <li>final ScheduledExecutorService scheduler = Executors  </li> <li>.newScheduledThreadPool(2);  </li> <li>final Runnable beeper = new Runnable() {  </li> <li>int count = 0;  </li> <li>public void run() {  </li> <li>System.out.println(new Date() + ” beep ” + (++count));  </li> <li>}  </li> <li>};  </li> <li>// 1U钟后运行,q每?U运行一?nbsp; </li> <li>final ScheduledFuture beeperHandle = scheduler.scheduleAtFixedRate(  </li> <li>beeper, 1, 2, SECONDS);  </li> <li>// 2U钟后运行,q每ơ在上次dq行完后{待5U后重新q行  </li> <li>final ScheduledFuture beeperHandle2 = scheduler  </li> <li>.scheduleWithFixedDelay(beeper, 2, 5, SECONDS);  </li> <li>// 30U后l束关闭dQƈ且关闭Scheduler  </li> <li>scheduler.schedule(new Runnable() {  </li> <li>public void run() {  </li> <li>beeperHandle.cancel(true);  </li> <li>beeperHandle2.cancel(true);  </li> <li>scheduler.shutdown();  </li> <li>}  </li> <li>}, 30, SECONDS);  </li> <li>}  </li> <li>}  </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() + ” beep ” + (++count)); } }; // 1U钟后运行,q每?U运行一? final ScheduledFuture beeperHandle = scheduler.scheduleAtFixedRate( beeper, 1, 2, SECONDS); // 2U钟后运行,q每ơ在上次dq行完后{待5U后重新q行 final ScheduledFuture beeperHandle2 = scheduler .scheduleWithFixedDelay(beeper, 2, 5, SECONDS); // 30U后l束关闭dQƈ且关闭Scheduler scheduler.schedule(new Runnable() { public void run() { beeperHandle.cancel(true); beeperHandle2.cancel(true); scheduler.shutdown(); } }, 30, SECONDS); } } </pre> <br /> Z(jin)退?gu)E,上面的代码中加入?jin)关闭Scheduler的操作。而对?4时q行的应用而言Q是没有必要关闭Scheduler的? <br /> <br /> 在实际应用中Q有时候需要多个线E同时工作以完成同一件事情,而且在完成过E中Q往往?x)等待其他线E都完成某一阶段后再执行Q等所有线E都到达某一个阶D后再统一执行? <br /> <br /> 比如有几个旅行团需要途经深圳、广州、韶兟뀁长沙最后到达武汉。旅行团中有自驾游的Q有徒步的,有乘坐旅游大巴的Q这些旅行团同时出发Qƈ且每C个目的地Q都要等待其他旅行团到达此地后再同时出发Q直到都到达l点站武汉? <br /> <br /> q时候C(j)yclicBarrier可以派上用场。CyclicBarrier最重要的属性就是参与者个敎ͼ另外最要方法是await()。当所有线E都调用?jin)await()后,pC些线E都可以l箋(hu)执行Q否则就?x)等待? <br /> <div> <div> <div>Java代码 <a 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 concurrent;  </li> <li>import java.text.SimpleDateFormat;  </li> <li>import java.util.Date;  </li> <li>import java.util.concurrent.BrokenBarrierException;  </li> <li>import java.util.concurrent.CyclicBarrier;  </li> <li>import java.util.concurrent.ExecutorService;  </li> <li>import java.util.concurrent.Executors;  </li> <li>public class TestCyclicBarrier {  </li> <li>// 徒步需要的旉: Shenzhen, Guangzhou, Shaoguan, Changsha, Wuhan  </li> <li>private static int[] timeWalk = { 5, 8, 15, 15, 10 };  </li> <li>// 自驾?nbsp; </li> <li>private static int[] timeSelf = { 1, 3, 4, 4, 5 };  </li> <li>// 旅游大巴  </li> <li>private static int[] timeBus = { 2, 4, 6, 6, 7 };  </li> <li>  </li> <li>static String now() {  </li> <li>SimpleDateFormat sdf = new SimpleDateFormat(“HH:mm:ss”);  </li> <li>return sdf.format(new Date()) + “: “;  </li> <li>}  </li> <li>  </li> <li>static class Tour implements Runnable {  </li> <li>private int[] times;  </li> <li>private CyclicBarrier barrier;  </li> <li>private String tourName;  </li> <li>public Tour(CyclicBarrier barrier, String tourName, int[] times) {  </li> <li>this.times = times;  </li> <li>this.tourName = tourName;  </li> <li>this.barrier = barrier;  </li> <li>}  </li> <li>public void run() {  </li> <li>try {  </li> <li>Thread.sleep(times[0] * 1000);  </li> <li>System.out.println(now() + tourName + ” Reached Shenzhen”);  </li> <li>barrier.await();  </li> <li>Thread.sleep(times[1] * 1000);  </li> <li>System.out.println(now() + tourName + ” Reached Guangzhou”);  </li> <li>barrier.await();  </li> <li>Thread.sleep(times[2] * 1000);  </li> <li>System.out.println(now() + tourName + ” Reached Shaoguan”);  </li> <li>barrier.await();  </li> <li>Thread.sleep(times[3] * 1000);  </li> <li>System.out.println(now() + tourName + ” Reached Changsha”);  </li> <li>barrier.await();  </li> <li>Thread.sleep(times[4] * 1000);  </li> <li>System.out.println(now() + tourName + ” Reached Wuhan”);  </li> <li>barrier.await();  </li> <li>} catch (InterruptedException e) {  </li> <li>} catch (BrokenBarrierException e) {  </li> <li>}  </li> <li>}  </li> <li>}  </li> <li>  </li> <li>public static void main(String[] args) {  </li> <li>// 三个旅行?nbsp; </li> <li>CyclicBarrier barrier = new CyclicBarrier(3);  </li> <li>ExecutorService exec = Executors.newFixedThreadPool(3);  </li> <li>exec.submit(new Tour(barrier, “WalkTour”, timeWalk));  </li> <li>exec.submit(new Tour(barrier, “SelfTour”, timeSelf));  </li> <li>exec.submit(new Tour(barrier, “BusTour”, timeBus));  </li> <li>exec.shutdown();  </li> <li>}  </li> <li>}  </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(“HH:mm:ss”); return sdf.format(new Date()) + “: “; } 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 + ” Reached Shenzhen”); barrier.await(); Thread.sleep(times[1] * 1000); System.out.println(now() + tourName + ” Reached Guangzhou”); barrier.await(); Thread.sleep(times[2] * 1000); System.out.println(now() + tourName + ” Reached Shaoguan”); barrier.await(); Thread.sleep(times[3] * 1000); System.out.println(now() + tourName + ” Reached Changsha”); barrier.await(); Thread.sleep(times[4] * 1000); System.out.println(now() + tourName + ” Reached Wuhan”); 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, “WalkTour”, timeWalk)); exec.submit(new Tour(barrier, “SelfTour”, timeSelf)); exec.submit(new Tour(barrier, “BusTour”, timeBus)); exec.shutdown(); } } </pre> <br /> q行l果Q? <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 /> q发库中的BlockingQueue是一个比较好玩的c,֐思义Q就是阻塞队列。该cM要提供了(jin)两个Ҏ(gu)put()和take()Q前者将一 个对象放到队列中Q如果队列已l满?jin),q待直到有I闲节点Q后者从head取一个对象,如果没有对象Q就{待直到有可取的对象? <br /> <br /> 下面的例子比较简单,一个读U程Q用于将要处理的文g对象d到阻塞队列中Q另外四个写U程用于取出文g对象Qؓ(f)?jin)模拟写操作耗时长的特点Q特? U程睡眠一D随机长度的旉。另外,该Demo也用到?jin)线E池和原子整型(AtomicIntegerQ,AtomicInteger可以在ƈ发情况下 辑ֈ原子化更斎ͼ避免使用?jin)synchronizedQ而且性能非常高。由于阻塞队列的put和take操作?x)阻塞,Z(jin)使线E退出,特在队列中添加了(jin)一 ?#8220;标识”Q算法中也叫“哨兵”Q当发现q个哨兵后,写线E就退出? <br /> <br /> 当然U程池也要显式退Z(jin)? <br /> <br /> <div> <div> <div>Java代码 <a 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 concurrent;  </li> <li>import java.io.File;  </li> <li>import java.io.FileFilter;  </li> <li>import java.util.concurrent.BlockingQueue;  </li> <li>import java.util.concurrent.ExecutorService;  </li> <li>import java.util.concurrent.Executors;  </li> <li>import java.util.concurrent.LinkedBlockingQueue;  </li> <li>import java.util.concurrent.atomic.AtomicInteger;  </li> <li>  </li> <li>public class TestBlockingQueue {  </li> <li>static long randomTime() {  </li> <li>return (long) (Math.random() * 1000);  </li> <li>}  </li> <li>  </li> <li>public static void main(String[] args) {  </li> <li>// 能容U?00个文?nbsp; </li> <li>final BlockingQueue queue = new LinkedBlockingQueue(100);  </li> <li>// U程?nbsp; </li> <li>final ExecutorService exec = Executors.newFixedThreadPool(5);  </li> <li>final File root = new File(“F:""JavaLib”);  </li> <li>// 完成标志  </li> <li>final File exitFile = new File(“”);  </li> <li>// M?nbsp; </li> <li>final AtomicInteger rc = new AtomicInteger();  </li> <li>// 写个?nbsp; </li> <li>final AtomicInteger wc = new AtomicInteger();  </li> <li>// ȝE?nbsp; </li> <li>Runnable read = new Runnable() {  </li> <li>public void run() {  </li> <li>scanFile(root);  </li> <li>scanFile(exitFile);  </li> <li>}  </li> <li>  </li> <li>public void scanFile(File file) {  </li> <li>if (file.isDirectory()) {  </li> <li>File[] files = file.listFiles(new FileFilter() {  </li> <li>public boolean accept(File pathname) {  </li> <li>return pathname.isDirectory()  </li> <li>|| pathname.getPath().endsWith(“.java”);  </li> <li>}  </li> <li>});  </li> <li>for (File one : files)  </li> <li>scanFile(one);  </li> <li>} else {  </li> <li>try {  </li> <li>int index = rc.incrementAndGet();  </li> <li>System.out.println(“Read0: ” + index + ” “  </li> <li>+ file.getPath());  </li> <li>queue.put(file);  </li> <li>} catch (InterruptedException e) {  </li> <li>}  </li> <li>}  </li> <li>}  </li> <li>};  </li> <li>exec.submit(read);  </li> <li>// 四个写线E?nbsp; </li> <li>for (int index = 0; index < 4; index++) {  </li> <li>// write thread  </li> <li>final int NO = index;  </li> <li>Runnable write = new Runnable() {  </li> <li>String threadName = “Write” + NO;  </li> <li>public void run() {  </li> <li>while (true) {  </li> <li>try {  </li> <li>Thread.sleep(randomTime());  </li> <li>int index = wc.incrementAndGet();  </li> <li>File file = queue.take();  </li> <li>// 队列已经无对?nbsp; </li> <li>if (file == exitFile) {  </li> <li>// 再次d”标志”Q以让其他线E正帔R?nbsp; </li> <li>queue.put(exitFile);  </li> <li>break;  </li> <li>}  </li> <li>System.out.println(threadName + “: ” + index + ” “  </li> <li>+ file.getPath());  </li> <li>} catch (InterruptedException e) {  </li> <li>}  </li> <li>}  </li> <li>}  </li> <li>};  </li> <li>exec.submit(write);  </li> <li>}  </li> <li>exec.shutdown();  </li> <li>}  </li> <li>}  </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) { // 能容U?00个文? final BlockingQueue queue = new LinkedBlockingQueue(100); // U程? final ExecutorService exec = Executors.newFixedThreadPool(5); final File root = new File(“F:""JavaLib”); // 完成标志 final File exitFile = new File(“”); // M? final AtomicInteger rc = new AtomicInteger(); // 写个? final AtomicInteger wc = new AtomicInteger(); // ȝE? 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(“.java”); } }); for (File one : files) scanFile(one); } else { try { int index = rc.incrementAndGet(); System.out.println(“Read0: ” + index + ” “ + file.getPath()); queue.put(file); } catch (InterruptedException e) { } } } }; exec.submit(read); // 四个写线E? for (int index = 0; index < 4; index++) { // write thread final int NO = index; Runnable write = new Runnable() { String threadName = “Write” + NO; public void run() { while (true) { try { Thread.sleep(randomTime()); int index = wc.incrementAndGet(); File file = queue.take(); // 队列已经无对? if (file == exitFile) { // 再次d”标志”Q以让其他线E正帔R? queue.put(exitFile); break; } System.out.println(threadName + “: ” + index + ” “ + file.getPath()); } catch (InterruptedException e) { } } } }; exec.submit(write); } exec.shutdown(); } } </pre> <br /> 从名字可以看出,CountDownLatch是一个倒数计数的锁Q当倒数?时触发事Ӟ也就是开锁,其他人就可以q入?jin)。在一些应用场合中Q需要等待某个条件达到要求后才能做后面的事情Q同时当U程都完成后也会(x)触发事gQ以便进行后面的操作? <br /> <br /> <br /> CountDownLatch最重要的方法是countDown()和await()Q前者主要是倒数一ơ,后者是{待倒数?Q如果没有到?Q就只有d{待?jin)? <br /> <br /> 一个CountDouwnLatch实例是不能重复用的Q也是说它是一ơ性的Q锁一l被打开׃能再关闭使用?jin),如果想重复用,误(g)虑使用CyclicBarrier? <br /> <br /> 下面的例子简单的说明?jin)CountDownLatch的用方法,模拟?00c跑,10名选手已经准备qAQ只{裁判一Co(h)下。当所有h都到辄Ҏ(gu)Q比赛结束? <br /> <br /> 同样Q线E池需要显式shutdown? <br /> <div> <div> <div>Java代码 <a 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 concurrent;  </li> <li>  </li> <li>import java.util.concurrent.CountDownLatch;  </li> <li>import java.util.concurrent.ExecutorService;  </li> <li>import java.util.concurrent.Executors;  </li> <li>  </li> <li>public class TestCountDownLatch {  </li> <li>public static void main(String[] args) throws InterruptedException {  </li> <li>// 开始的倒数?nbsp; </li> <li>final CountDownLatch begin = new CountDownLatch(1);  </li> <li>// l束的倒数?nbsp; </li> <li>final CountDownLatch end = new CountDownLatch(10);  </li> <li>// 十名选手  </li> <li>final ExecutorService exec = Executors.newFixedThreadPool(10);  </li> <li>for(int index = 0; index < 10; index++) {  </li> <li>final int NO = index + 1;  </li> <li>Runnable run = new Runnable(){  </li> <li>public void run() {  </li> <li>try {  </li> <li>begin.await();  </li> <li>Thread.sleep((long) (Math.random() * 10000));  </li> <li>System.out.println(“No.” + NO + ” arrived”);  </li> <li>} catch (InterruptedException e) {  </li> <li>} finally {  </li> <li>end.countDown();  </li> <li>}  </li> <li>}  </li> <li>};  </li> <li>exec.submit(run);  </li> <li>}  </li> <li>System.out.println(“Game Start”);  </li> <li>begin.countDown();  </li> <li>end.await();  </li> <li>System.out.println(“Game Over”);  </li> <li>exec.shutdown();  </li> <li>}  </li> <li>}  </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); // l束的倒数? final CountDownLatch end = new CountDownLatch(10); // 十名选手 final ExecutorService exec = Executors.newFixedThreadPool(10); for(int index = 0; index < 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(“No.” + NO + ” arrived”); } catch (InterruptedException e) { } finally { end.countDown(); } } }; exec.submit(run); } System.out.println(“Game Start”); begin.countDown(); end.await(); System.out.println(“Game Over”); exec.shutdown(); } } </pre> <br /> q行l果: <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 /> 有时候在实际应用中,某些操作很耗时Q但又不是不可或~的步骤。比如用|页览器浏览新LQ最重要的是要显C文字内容,至于与新ȝ匚w的图? 没有那么重要的Q所以此旉先保证文字信息先昄Q而图片信息会(x)后显C,但又不能不显C,׃下蝲囄是一个耗时的操作,所以必M开始就得下载? <br /> <br /> <br /> Java的ƈ发库的Futurecd可以满q个要求。Future的重要方法包括get()和cancel()Qget()获取数据对象Q如? 数据没有加蝲Q就?x)阻塞直到取到数据,? cancel()是取消数据加载。另外一个get(timeout)操作Q表C如果在timeout旉内没有取到就p|q回Q而不再阻塞? <br /> <br /> 下面的Demo单的说明?jin)Future的用方法:(x)一个非常耗时的操作必M开始启动,但又不能一直等待;其他重要的事情又必须做,{完成后Q就可以做不重要的事情? <br /> <div> <div> <div>Java代码 <a 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 concurrent;  </li> <li>  </li> <li>import java.util.concurrent.Callable;  </li> <li>import java.util.concurrent.ExecutionException;  </li> <li>import java.util.concurrent.ExecutorService;  </li> <li>import java.util.concurrent.Executors;  </li> <li>import java.util.concurrent.Future;  </li> <li>  </li> <li>public class TestFutureTask {  </li> <li>public static void main(String[] args)throws InterruptedException,  </li> <li>ExecutionException {  </li> <li>final ExecutorService exec = Executors.newFixedThreadPool(5);  </li> <li>Callable call = new Callable() {  </li> <li>public String call() throws Exception {  </li> <li>Thread.sleep(1000 * 5);  </li> <li>return “Other less important but longtime things.”;  </li> <li>}  </li> <li>};  </li> <li>Future task = exec.submit(call);  </li> <li>// 重要的事?nbsp; </li> <li>Thread.sleep(1000 * 3);  </li> <li>System.out.println(“Let’s do important things.”);  </li> <li>// 其他不重要的事情  </li> <li>String obj = task.get();  </li> <li>System.out.println(obj);  </li> <li>// 关闭U程?nbsp; </li> <li>exec.shutdown();  </li> <li>}  </li> <li>}  </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 “Other less important but longtime things.”; } }; Future task = exec.submit(call); // 重要的事? Thread.sleep(1000 * 3); System.out.println(“Let’s do important things.”); // 其他不重要的事情 String obj = task.get(); System.out.println(obj); // 关闭U程? exec.shutdown(); } } </pre> <br /> q行l果Q? <br /> Let’s do important things. <br /> Other less important but longtime things. <br /> <br /> 考虑以下场景Q浏览网|Q浏览器?个线E下载网中的图片文Ӟ׃囄大小、网站访问速度{诸多因素的影响Q完成图片下载的旉׃(x)有很大的不同。如果先下蝲完成的图片就?x)被先显C到界面上,反之Q后下蝲的图片就后显C? <br /> <br /> <br /> Java的ƈ发库的CompletionService可以满q种场景要求。该接口有两个重要方法:(x)submit()和take()? submit用于提交一个runnable或者callableQ一般会(x)提交l一个线E池处理Q而take是取出已经执行完毕r(sh)unnable或? callable实例的Future对象Q如果没有满求的Q就{待?jin)? CompletionServiceq有一个对应的Ҏ(gu)pollQ该Ҏ(gu)与takecMQ只是不?x)等待,如果没有满要求Q就q回null对象? <br /> <div> <div> <div>Java代码 <a 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 concurrent;  </li> <li>  </li> <li>import java.util.concurrent.Callable;  </li> <li>import java.util.concurrent.CompletionService;  </li> <li>import java.util.concurrent.ExecutionException;  </li> <li>import java.util.concurrent.ExecutorCompletionService;  </li> <li>import java.util.concurrent.ExecutorService;  </li> <li>import java.util.concurrent.Executors;  </li> <li>import java.util.concurrent.Future;  </li> <li>  </li> <li>public class TestCompletionService {  </li> <li>public static void main(String[] args) throws InterruptedException,  </li> <li>ExecutionException {  </li> <li>ExecutorService exec = Executors.newFixedThreadPool(10);  </li> <li>CompletionService serv =  </li> <li>new ExecutorCompletionService(exec);  </li> <li>  </li> <li>for (int index = 0; index < 5; index++) {  </li> <li>final int NO = index;  </li> <li>Callable downImg = new Callable() {  </li> <li>public String call() throws Exception {  </li> <li>Thread.sleep((long) (Math.random() * 10000));  </li> <li>return “Downloaded Image ” + NO;  </li> <li>}  </li> <li>};  </li> <li>serv.submit(downImg);  </li> <li>}  </li> <li>  </li> <li>Thread.sleep(1000 * 2);  </li> <li>System.out.println(“Show web content”);  </li> <li>for (int index = 0; index < 5; index++) {  </li> <li>Future task = serv.take();  </li> <li>String img = task.get();  </li> <li>System.out.println(img);  </li> <li>}  </li> <li>System.out.println(“End”);  </li> <li>// 关闭U程?nbsp; </li> <li>exec.shutdown();  </li> <li>}  </li> <li>}  </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 < 5; index++) { final int NO = index; Callable downImg = new Callable() { public String call() throws Exception { Thread.sleep((long) (Math.random() * 10000)); return “Downloaded Image ” + NO; } }; serv.submit(downImg); } Thread.sleep(1000 * 2); System.out.println(“Show web content”); for (int index = 0; index < 5; index++) { Future task = serv.take(); String img = task.get(); System.out.println(img); } System.out.println(“End”); // 关闭U程? exec.shutdown(); } } </pre> <br /> q行l果: <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 /> 操作pȝ的信号量是个很重要的概念Q在q程控制斚w都有应用。Javaq发库的Semaphore可以很轻村֮成信号量控制QSemaphore 可以控制某个资源可被同时讉K的个敎ͼacquire()获取一个许可,如果没有q待,而release()释放一个许可。比如在Windows下可? 讄׃n文g的最大客L(fng)讉K个数? <br /> <br /> Semaphorel护?jin)当前访问的个数Q提供同步机Ӟ控制同时讉K的个数。在数据l构中链表可以保?#8220;无限”的节点,用Semaphore可以实现有限大小的链表。另外重入锁ReentrantLock也可以实现该功能Q但实现上要负责些,代码也要复杂些? <br /> <br /> 下面的Demo中申明了(jin)一个只?个许可的SemaphoreQ而有20个线E要讉Kq个资源Q通过acquire()和release()获取和释放访问许可? <br /> <div> <div> <div>Java代码 <a 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 concurrent;  </li> <li>  </li> <li>import java.util.concurrent.ExecutorService;  </li> <li>import java.util.concurrent.Executors;  </li> <li>import java.util.concurrent.Semaphore;  </li> <li>  </li> <li>public class TestSemaphore {  </li> <li>public static void main(String[] args) {  </li> <li>// U程?nbsp; </li> <li>ExecutorService exec = Executors.newCachedThreadPool();  </li> <li>// 只能5个线E同时访?nbsp; </li> <li>final Semaphore semp = new Semaphore(5);  </li> <li>// 模拟20个客L(fng)讉K  </li> <li>for (int index = 0; index < 20; index++) {  </li> <li>final int NO = index;  </li> <li>Runnable run = new Runnable() {  </li> <li>public void run() {  </li> <li>try {  </li> <li>// 获取许可  </li> <li>semp.acquire();  </li> <li>System.out.println(“Accessing: ” + NO);  </li> <li>Thread.sleep((long) (Math.random() * 10000));  </li> <li>// 讉K完后Q释?nbsp; </li> <li>semp.release();  </li> <li>} catch (InterruptedException e) {  </li> <li>}  </li> <li>}  </li> <li>};  </li> <li>exec.execute(run);  </li> <li>}  </li> <li>// 退出线E池  </li> <li>exec.shutdown();  </li> <li>}  </li> <li>}  </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) { // U程? ExecutorService exec = Executors.newCachedThreadPool(); // 只能5个线E同时访? final Semaphore semp = new Semaphore(5); // 模拟20个客L(fng)讉K for (int index = 0; index < 20; index++) { final int NO = index; Runnable run = new Runnable() { public void run() { try { // 获取许可 semp.acquire(); System.out.println(“Accessing: ” + NO); Thread.sleep((long) (Math.random() * 10000)); // 讉K完后Q释? semp.release(); } catch (InterruptedException e) { } } }; exec.execute(run); } // 退出线E池 exec.shutdown(); } } </pre> <br /> q行l果Q? <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.tkk7.com/java-blog/aggbug/193845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-04-17 19:11 <a href="http://www.tkk7.com/java-blog/articles/193845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Sun HotSpot 1.4.1 JVM堆大的调整http://www.tkk7.com/java-blog/articles/193455.html一步一步努力向上爬一步一步努力向上爬Wed, 16 Apr 2008 07:19:00 GMThttp://www.tkk7.com/java-blog/articles/193455.htmlhttp://www.tkk7.com/java-blog/comments/193455.htmlhttp://www.tkk7.com/java-blog/articles/193455.html#Feedback0http://www.tkk7.com/java-blog/comments/commentRss/193455.htmlhttp://www.tkk7.com/java-blog/services/trackbacks/193455.html
Sun HotSpot 1.4.1 JVM堆大的调整
    
    Sun HotSpot 1.4.1使用分代攉器,它把堆分Z个主要的域:(x)新域、旧域以?qing)永久域。Jvm生成的所有新对象攑֜新域中。一旦对象经历了(jin)一定数量的垃圾攉循环 后,便获得用期q进入旧域。在怹域中jvm则存储class和method对象。就配置而言Q永久域是一个独立域q且不认为是堆的一部分?br />
    下面介绍如何控制q些域的大小。可使用-Xms?Xmx 控制整个堆的原始大小或最大倹{?br />     下面的命令是把初始大设|ؓ(f)128MQ?br />     java –Xms128m
     –Xmx256m为控制新域的大小Q可使用-XX:NewRatio讄新域在堆中所占的比例?br />
   下面的命令把整个堆设|成128mQ新域比率设|成3Q即新域与旧域比例ؓ(f)1Q?Q新域ؓ(f)堆的1/4?2MQ?br />    java –Xms128m –Xmx128m
    –XX:NewRatio =3可?XX:NewSize?XX:MaxNewsize讄新域的初始值和最大倹{?br />
   下面的命令把新域的初始值和最大D|成64m:
     java –Xms256m –Xmx256m –Xmn64m
   怹域默认大ؓ(f)4m。运行程序时Qjvm?x)调整永久域的大以满需要。每ơ调整时Qjvm?x)对堆进行一ơ完全的垃圾攉?br />
   使用-XX:MaxPerSize标志来增加永久域搭大。在WebLogic Server应用E序加蝲较多cLQ经帔R要增加永久域的最大倹{当jvm加蝲cLQ永久域中的对象急剧增加Q从而jvm不断调整怹域大。ؓ(f)?jin)避? 调整Q可使用-XX:PerSize标志讄初始倹{?br />    下面把永久域初始D|成32mQ最大D|成64m?br />     java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m

     默认状态下QHotSpot在新域中使用复制攉器。该域一般分Z个部分。第一部分为EdenQ用于生成新的对象。另两部分称为救助空_(d)当Eden? 满时Q收集器停止应用E序Q把所有可到达对象复制到当前的from救助I间Q一旦当前的from救助I间充满Q收集器则把可到辑֯象复制到当前的to救助 I间。From和to救助I间互换角色。维持活动的对象在救助I间不断复制Q直到它们获得用期q{入旧域。?XX:SurvivorRatio? 控制新域子空间的大小?br />
    同NewRation一PSurvivorRation规定某救助域与EdenI间的比倹{比如,以下命o(h)把新域设|成64mQEden?2mQ每个救助域各占16mQ?br />     java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2

     如前所qͼ默认状态下HotSpotҎ(gu)域用复制收集器Q对旧域使用标记Q清除-压羃攉器。在新域中用复制收集器有很多意义,因ؓ(f)应用E序生成的大 部分对象是短寿命的。理想状态下Q所有过渡对象在UdEdenI间时将被收集。如果能够这L(fng)话,q且UdEdenI间的对象是长寿命的Q那么理Z可以 立即把它们移q旧域,避免在救助空间反复复制。但是,应用E序不能适合q种理想状态,因ؓ(f)它们有一部分中长寿命的对象。最好是保持q些中长寿命的对象ƈ 攑֜新域中,因ؓ(f)复制部分的对象L压羃旧域廉h(hun)。ؓ(f)控制新域中对象的复制Q可?XX:TargetSurvivorRatio控制救助I间的比? Q该值是讄救助I间的用比例。如救助I间?MQ该?0表示可用500KQ。该值是一个百分比Q默认值是50。当较大的堆栈用较低的 sruvivorratioӞ应增加该值到80?0Q以更好利用救助I间。用-XX:maxtenuring threshold可控制上限?br />
   为放|所有的复制全部发生以及(qing)希望对象从eden扩展到旧域,可以把MaxTenuring Threshold讄?。设|完成后Q实际上׃再用救助空间了(jin)Q因此应把SurvivorRatio设成最大g最大化EdenI间Q设|如下:(x)
   java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatioQ?0000 …


]]>
一个很耗时的运需要缓存其计算l果Q采用备忘录模式实现http://www.tkk7.com/java-blog/articles/191992.html一步一步努力向上爬一步一步努力向上爬Thu, 10 Apr 2008 14:30:00 GMThttp://www.tkk7.com/java-blog/articles/191992.htmlhttp://www.tkk7.com/java-blog/comments/191992.htmlhttp://www.tkk7.com/java-blog/articles/191992.html#Feedback0http://www.tkk7.com/java-blog/comments/commentRss/191992.htmlhttp://www.tkk7.com/java-blog/services/trackbacks/191992.html
Java代码 
  1. public interface Computable<A, V> {  
  2.     V compute(A arg) throws InterruptedException;  
  3. }  
  4.   
  5. public class ExpensiveFunction  
  6.         implements Computable<String, BigInteger> {  
  7.     public BigInteger compute(String arg) {  
  8.         // 假设q里非常耗时...  
  9.         return new BigInteger(arg);  
  10.     }  
  11. }  


备忘录缓存方案一Q?
Java代码 
  1. public class Memoizer1<A, V> implements Computable<A, V> {  
  2.     @GuardedBy("this")  
  3.     private final Map<A, V> cache = new HashMap<A, V>();  
  4.     private final Computable<A, V> c;  
  5.   
  6.     public Memoizer1(Computable<A, V> c) {  
  7.         this.c = c;  
  8.     }  
  9.   
  10.     public synchronized V compute(A arg) throws InterruptedException {  
  11.         V result = cache.get(arg);  
  12.         if (result == null) {  
  13.             result = c.compute(arg);  
  14.             cache.put(arg, result);  
  15.         }  
  16.         return result;  
  17.     }  
  18. }  

q里备忘录的整个computeq程被同步,相当于我最原始的低效方案,


备忘录缓存方案二Q?
Java代码 
  1. public class Memoizer2<A, V> implements Computable<A, V> {  
  2.     private final Map<A, V> cache = new ConcurrentHashMap<A, V>();  
  3.     private final Computable<A, V> c;  
  4.   
  5.     public Memoizer2(Computable<A, V> c) { this.c = c; }  
  6.   
  7.     public V compute(A arg) throws InterruptedException {  
  8.         V result = cache.get(arg);  
  9.         if (result == null) {  
  10.             result = c.compute(arg);  
  11.             cache.put(arg, result);  
  12.         }  
  13.         return result;  
  14.     }  
  15. }  

线E安全性委lcacheQ注Q这个方案的cache用了(jin)ConcurrentHashMapQ它是线E安全的?

备忘录缓存方案三Q?
Java代码 
  1. public class Memoizer3<A, V> implements Computable<A, V> {  
  2.     private final Map<A, Future<V>> cache  
  3.             = new ConcurrentHashMap<A, Future<V>>();  
  4.     private final Computable<A, V> c;  
  5.   
  6.     public Memoizer3(Computable<A, V> c) { this.c = c; }  
  7.   
  8.     public V compute(final A arg) throws InterruptedException {  
  9.         Future<V> f = cache.get(arg);  
  10.         if (f == null) {  
  11.             Callable<V> eval = new Callable<V>() {  
  12.                 public V call() throws InterruptedException {  
  13.                     return c.compute(arg);  
  14.                 }  
  15.             };  
  16.             FutureTask<V> ft = new FutureTask<V>(eval);  
  17.             f = ft;  
  18.             cache.put(arg, ft);  
  19.             ft.run(); // call to c.compute happens here  
  20.         }  
  21.         try {  
  22.             return f.get();  
  23.         } catch (ExecutionException e) {  
  24.             throw launderThrowable(e.getCause());  
  25.         }  
  26.     }  
  27. }  

使用Future(相当上一帖的Entry)装Q因里资源获取过E不固定(通用Ҏ(gu))Q所以用了(jin)Callableq行回调资源获取q程(求?Q?
q个Ҏ(gu)?if (f == null) 不安全,Ҏ(gu)性可能会(x)q行多次q算Q下面的Ҏ(gu)四解册个问题?

备忘录缓存方案四Q最l方案)(j)Q?
Java代码 
  1. public class Memoizer<A, V> implements Computable<A, V> {  
  2.     private final ConcurrentMap<A, Future<V>> cache  
  3.         = new ConcurrentHashMap<A, Future<V>>();  
  4.     private final Computable<A, V> c;  
  5.   
  6.     public Memoizer(Computable<A, V> c) { this.c = c; }  
  7.   
  8.     public V compute(final A arg) throws InterruptedException {  
  9.         while (true) {  
  10.             Future<V> f = cache.get(arg);  
  11.             if (f == null) {  
  12.                 Callable<V> eval = new Callable<V>() {  
  13.                     public V call() throws InterruptedException {  
  14.                         return c.compute(arg);  
  15.                     }  
  16.                 };  
  17.                 FutureTask<V> ft = new FutureTask<V>(eval);  
  18.                 f = cache.putIfAbsent(arg, ft);  
  19.                 if (f == null) { f = ft; ft.run(); }  
  20.             }  
  21.             try {  
  22.                 return f.get();  
  23.             } catch (CancellationException e) {  
  24.                 cache.remove(arg, f);  
  25.             } catch (ExecutionException e) {  
  26.                 throw launderThrowable(e.getCause());  
  27.             }  
  28.         }  
  29.     }  



]]>
Java]用OSCacheq行~存对象http://www.tkk7.com/java-blog/articles/191952.html一步一步努力向上爬一步一步努力向上爬Thu, 10 Apr 2008 10:13:00 GMThttp://www.tkk7.com/java-blog/articles/191952.htmlhttp://www.tkk7.com/java-blog/comments/191952.htmlhttp://www.tkk7.com/java-blog/articles/191952.html#Feedback0http://www.tkk7.com/java-blog/comments/commentRss/191952.htmlhttp://www.tkk7.com/java-blog/services/trackbacks/191952.html
1、OSCache是什?
     OSCache标记库由O(jin)penSymphony设计Q它是一U开创性的~存Ҏ(gu)Q它提供?jin)在现有JSP面之内实现内存~存的功能。OSCache是个 一个被q泛采用的高性能的J2EE~存框架QOSCacheq能应用于Q何Java应用E序的普通的~存解决Ҏ(gu)?br /> 2、OSCache的特?/strong>
    (1) ~存?sh)M对象Q你可以不受限制的缓存部分jsp面或HTTPhQQ何java对象都可以缓存?br />     (2) 拥有全面的APIQOSCache API允许你通过~程的方式来控制所有的OSCacheҎ(gu)?
    (3) 怹~存Q缓存能被配|写入硬盘,因此允许在应用服务器的多ơ生命周期间~存创徏开销昂贵的数据?
    (4) 支持集群Q集缓存数据能被单个的q行参数配置Q不需要修改代码?br />     (5) ~存q期Q你可以有最大限度的控制~存对象的过期,包括可插入式的刷新策略(如果默认性能不能满需要时Q?br /> 3、OSCache的安装与配置
    |上已经有一个不错的使用教程Q?a target="_blank">http://blog.csdn.net/ezerg/archive/2004/10/14/135769.aspx
4、有?#8220;用OSCacheq行~存对象”的研I?/strong>
    q个是我今天要说的东ѝ网上对于OSCache~存Web面很多说明和例子,但对于缓存对象方面说得不多,我就把自已写得一些东西放出来Q让大家看一看是怎样~存对象?
    我基于GeneralCacheAdministratorcL写的BaseCachec?br />    
  1. package com.klstudio.cache;   
  2.   
  3. import java.util.Date;   
  4.   
  5. import com.opensymphony.oscache.base.NeedsRefreshException;   
  6. import com.opensymphony.oscache.general.GeneralCacheAdministrator;   
  7.   
  8. public class BaseCache extends GeneralCacheAdministrator {   
  9.     //q期旉(单位为秒);   
  10.     private int refreshPeriod;   
  11.     //关键字前~字符;   
  12.     private String keyPrefix;   
  13.        
  14.     private static final long serialVersionUID = -4397192926052141162L;   
  15.        
  16.     public BaseCache(String keyPrefix,int refreshPeriod){   
  17.         super();   
  18.         this.keyPrefix = keyPrefix;   
  19.         this.refreshPeriod = refreshPeriod;   
  20.     }   
  21.     //d被缓存的对象;   
  22.     public void put(String key,Object value){   
  23.         this.putInCache(this.keyPrefix+"_"+key,value);   
  24.     }   
  25.     //删除被缓存的对象;   
  26.     public void remove(String key){   
  27.         this.flushEntry(this.keyPrefix+"_"+key);   
  28.     }   
  29.     //删除所有被~存的对?   
  30.     public void removeAll(Date date){   
  31.         this.flushAll(date);   
  32.     }   
  33.        
  34.     public void removeAll(){   
  35.         this.flushAll();   
  36.     }   
  37.     //获取被缓存的对象;   
  38.     public Object get(String key) throws Exception{   
  39.         try{   
  40.             return this.getFromCache(this.keyPrefix+"_"+key,this.refreshPeriod);   
  41.         } catch (NeedsRefreshException e) {   
  42.             this.cancelUpdate(this.keyPrefix+"_"+key);   
  43.             throw e;   
  44.         }   
  45.   
  46.     }   
  47.        
  48. }   
  49.   
  50.   

   通过CacheManagercL看怎样~存对象?q个cM所用的News只是具体功能的类Q我׃贴出来了(jin)Q你可以自己写一?
   
  1. package com.klstudio;   
  2.   
  3. import com.klstudio.News;   
  4. import com.klstudio.cache.BaseCache;   
  5.   
  6. public class CacheManager {   
  7.        
  8.     private BaseCache newsCache;   
  9.   
  10.        
  11.     private static CacheManager instance;   
  12.     private static Object lock = new Object();   
  13.        
  14.     public CacheManager() {   
  15.         //q个Ҏ(gu)配置文g来,初始BaseCache而已;   
  16.         newsCache = new BaseCache("news",1800);        
  17.     }   
  18.        
  19.     public static CacheManager getInstance(){   
  20.         if (instance == null){   
  21.             synchronized( lock ){   
  22.                 if (instance == null){   
  23.                     instance = new CacheManager();   
  24.                 }   
  25.             }   
  26.         }   
  27.         return instance;   
  28.     }   
  29.   
  30.     public void putNews(News news) {   
  31.         // TODO 自动生成Ҏ(gu)存根   
  32.         newsCache.put(news.getID(),news);   
  33.     }   
  34.   
  35.     public void removeNews(String newsID) {   
  36.         // TODO 自动生成Ҏ(gu)存根   
  37.         newsCache.remove(newsID);   
  38.     }   
  39.   
  40.     public News getNews(String newsID) {   
  41.         // TODO 自动生成Ҏ(gu)存根   
  42.         try {   
  43.             return (News) newsCache.get(newsID);   
  44.         } catch (Exception e) {   
  45.             // TODO 自动生成 catch ?  
  46.             System.out.println("getNews>>newsID["+newsID+"]>>"+e.getMessage());   
  47.             News news = new News(newsID);   
  48.             this.putNews(news);   
  49.             return news;   
  50.         }   
  51.     }   
  52.   
  53.     public void removeAllNews() {   
  54.         // TODO 自动生成Ҏ(gu)存根   
  55.         newsCache.removeAll();   
  56.     }   
  57.   
  58. }   
  59.   


]]>
JAVA STRING FORMAT ?/title><link>http://www.tkk7.com/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.tkk7.com/java-blog/articles/189040.html</guid><wfw:comment>http://www.tkk7.com/java-blog/comments/189040.html</wfw:comment><comments>http://www.tkk7.com/java-blog/articles/189040.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/java-blog/comments/commentRss/189040.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/java-blog/services/trackbacks/189040.html</trackback:ping><description><![CDATA[<p><span style="font-size: 10.5pt;">JDK1.5中,StringcL增了(jin)一个很有用的静(rn)态方法String.format():<br /> format(Locale l, String format, Object... args) 使用指定的语a环境、格式字W串和参数返回一个格式化字符丌Ӏ?br /> format(String format, Object... args) 使用指定的格式字W串和参数返回一个格式化字符丌Ӏ?br /> <br /> 丑և个这个方法实用的例子(注释是输出结?Q?</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);   // "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);                // "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);              // "00123"</code>是不是很方便Q让人动?j)啊Q哈哈,q有更多的效?<br /> <br /> ? 实format函数有些cMc语言中printf函数Q一些格式字W串?C cMQ但已进行了(jin)某些定制Q以适应 Java 语言Qƈ且利用了(jin)其中一些特性。此Ҏ(gu)提供?jin)对布局寚w和排列的支持Q以?qing)对数倹{字W串和日?旉数据的常规格式和特定于语a环境的输出的支持。支? 诸如 byte、BigDecimal ?Calendar {常?Java cd?br /> <br /> 产生格式化输出的每个Ҏ(gu)都需要格式字W串 和参数列表。格式字W串是一?StringQ它可以包含固定文本以及(qing)一个或多个嵌入的格式说明符。请考虑以下CZQ?br /> <br /> Calendar c = ...;<br /> String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);<br /> <br /> ? 式字W串?format Ҏ(gu)的第一个参数。它包含三个格式说明W?"%1$tm"?%1$te" ? "%1$tY"Q它们指出应该如何处理参C?qing)在文本的什么地Ҏ(gu)入它们。格式字W串的其余部分是包括 "Dukes Birthday: " 和其他Q何空格或标点W号的固定文本?参数列表׃递给位于格式字符串之后的Ҏ(gu)的所有参数组成。在上述CZ中,参数列表的大ؓ(f) 1Q由新对? Calendar l成?br /> <br /> <strong>1.常规cd、字W类型和数值类型的格式说明W的语法如下Q?/strong>%[argument_index$][flags][width][.precision]conversion<br /> <br /> 可选的 <em>argument_index</em> 是一个十q制整数Q用于表明参数在参数列表中的位置。第一个参数由 "1$" 引用Q第二个参数?"2$" 引用Q依此类推?br /> 可选的 <em>flags</em> 是修改输出格式的字符集。有效标志的集合取决于{换类型?br /> 可?<em>width</em> 是一个非负十q制整数Q表明要向输Z写入的最字W数?br /> 可?<em>precision</em> 是一个非负十q制整数Q通常用来限制字符数。特定行为取决于转换cd?br /> 所需?<em>conversion</em> 是一个表明应该如何格式化参数的字W。给定参数的有效转换集合取决于参数的数据cd?br /> <br /> <strong>2.用来表示日期和时间类型的格式说明W的语法如下:</strong><br /> %[argument_index$][flags][width]conversion<br /> <br /> 可选的 <em>argument_index</em>?em>flags</em> ?<em>width</em> 的定义同上?br /> 所需?<em>conversion</em> 是一个由两字W组成的序列。第一个字W是 't' ?'T'。第二个字符表明所使用的格式。这些字W类g但不完全{同于那些由 GNU date ?POSIX strftime(3c) 定义的字W?<br /> <br /> <br /> <strong>3.与参C对应的格式说明符的语法如下:(x)</strong><br /> %[flags][width]conversion<br /> <br /> 可?<em>flags</em> ?<em>width</em> 的定义同上?br /> 所需?<em>conversion</em> 是一个表明要在输Z所插内容的字符?<br /> <br /> <font size="4"><strong>转换</strong></font><br /> 转换可分Z下几c:(x)<br /> 1. 常规 - 可应用于M参数cd<br /> 2. 字符 - 可应用于表示 Unicode 字符的基本类型:(x)char、Character、byte、Byte、short ?Short。当 Character.isValidCodePoint(int) q回 true Ӟ可将此{换应用于 int ?Integer cd<br /> 3. 数?br />       1. 整数 - 可应用于 Java 的整数类型:(x)byte、Byte、short、Short、int、Integer、long、Long ?BigInteger<br />       2. 点 - 可用?Java 的Q点类型:(x)float、Float、double、Double ?BigDecimal <br /> 4. 日期/旉 - 可应用于 Java 的、能够对日期或时间进行编码的cdQlong、Long、Calendar ?Date?br /> 5. 癑ֈ?- 产生字面?'%' ('"u0025')<br /> 6. 行分隔符 - 产生特定于^台的行分隔符<br /> <br /> ? 表ȝ?jin)受支持的{换。由大写字符Q如 'B'?H'?S'?C'?X'?E'?G'?A' ? 'T'Q表C的转换与由相应的小写字W的转换{同Q根据流行的 Locale 规则结果{换ؓ(f)大写形式除外。后者等同于 String.toUpperCase() 的以下调?<br /> <br /> </p> <table align="center" cellspacing="0"> <tbody> <tr> <td>转换</td> <td>参数cd</td> <td>说明</td> </tr> <tr> <td>'b', 'B' </td> <td>常规 </td> <td>如果参数 <em>arg</em> ?nullQ则l果?"false"。如?<em>arg</em> 是一?boolean 值或 <a target="_blank">Boolean</a>Q则l果?<a target="_blank">String.valueOf()</a> q回的字W串。否则结果ؓ(f) "true"?/td> </tr> <tr> <td>'h', 'H' </td> <td>常规 </td> <td>如果参数 <em>arg</em> ?nullQ则l果?"null"。否则,l果?Integer.toHexString(arg.hashCode()) 得到的结果?/td> </tr> <tr> <td>'s', 'S' </td> <td>常规 </td> <td>如果参数 <em>arg</em> ?nullQ则l果?"null"。如?<em>arg</em> 实现 <a target="_blank">Formattable</a>Q则调用 <a target="_blank">arg.formatTo</a>。否则,l果?arg.toString() 得到的结果?/td> </tr> <tr> <td>'c', 'C' </td> <td>字符 </td> <td>l果是一?Unicode 字符</td> </tr> <tr> <td>'d' </td> <td>整数 </td> <td>l果被格式化为十q制整数</td> </tr> <tr> <td>'o' </td> <td>整数 </td> <td>l果被格式化为八q制整数</td> </tr> <tr> <td>'x', 'X' </td> <td>整数 </td> <td>l果被格式化为十六进制整?/td> </tr> <tr> <td>'e', 'E' </td> <td>点 </td> <td>l果被格式化为用计算机科学记数法表示的十q制?/td> </tr> <tr> <td>'f' </td> <td>点 </td> <td>l果被格式化为十q制?/td> </tr> <tr> <td>'g', 'G' </td> <td>点 </td> <td>Ҏ(gu)_ֺ和舍入运后的|使用计算机科学记数Ş式或十进制格式对l果q行格式化?/td> </tr> <tr> <td>'a', 'A' </td> <td>点 </td> <td>l果被格式化为带有效位数和指数的十六q制点?/td> </tr> <tr> <td>'t', 'T' </td> <td>日期/旉 </td> <td>日期和时间{换字W的前缀。请参阅<a target="_blank">日期/旉转换</a>?/td> </tr> <tr> <td>'%' </td> <td>癑ֈ?</td> <td>l果为字面?'%' ('"u0025')</td> </tr> <tr> <td>'n' </td> <td>行分隔符 </td> <td>l果为特定于q_的行分隔W?/td> </tr> </tbody> </table> <br /> M未明定义ؓ(f)转换的字W都是非法字W,q且都被保留Q以供将来扩展用?br /> <br /> <font size="4"><strong>日期/旉转换<br /> </strong></font>? 下日期和旉转换的后~字符是ؓ(f) 't' ?'T' 转换定义的。这些类型相g但不完全{同于那些由 GNU date ?POSIX strftime(3c) 定义的类型。提供其他{换类型是Z(jin)讉K特定?Java 的功能(如将 'L' 用作U中的毫U)(j)?br /> <br /> 以下转换字符用来格式化时_(d)(x)<br /> <br /> <table align="center" cellspacing="0"> <tbody> <tr> <td>'H' </td> <td>24 时制的时Q被格式化ؓ(f)必要时带前导零的两位敎ͼ?00 - 23?/td> </tr> <tr> <td>'I' </td> <td>12 时制的时Q被格式化ؓ(f)必要时带前导零的两位敎ͼ?01 - 12?/td> </tr> <tr> <td>'k' </td> <td>24 时制的时Q即 0 - 23?/td> </tr> <tr> <td>'l' </td> <td>12 时制的时Q即 1 - 12?/td> </tr> <tr> <td>'M' </td> <td>时中的分钟Q被格式化ؓ(f)必要时带前导零的两位敎ͼ?00 - 59?/td> </tr> <tr> <td>'S' </td> <td>分钟中的U,被格式化为必要时带前导零的两位数Q即 00 - 60 Q?60" 是支持闰U所需的一个特D|(j)?/td> </tr> <tr> <td>'L' </td> <td>U中的毫U,被格式化为必要时带前导零的三位数Q即 000 - 999?/td> </tr> <tr> <td>'N' </td> <td>U中的毫微秒Q被格式化ؓ(f)必要时带前导零的?ji)位敎ͼ?000000000 - 999999999?/td> </tr> <tr> <td>'p' </td> <td>特定于语a环境?<a target="_blank">上午或下?/a> 标记以小写Ş式表C,例如 "am" ?"pm"。用{换前~ 'T' 可以此输出转换为大写Ş式?/td> </tr> <tr> <td>'z' </td> <td>相对?GMT ?<a target="_blank">RFC 822</a> 格式的数字时区偏U量Q例?-0800?/td> </tr> <tr> <td>'Z' </td> <td>表示时区~写形式的字W串。Formatter 的语a环境?yu)取代参数的语言环境Q如果有Q?/td> </tr> <tr> <td>'s' </td> <td>自协调世界时 (UTC) 1970 q?1 ?1 ?00:00:00 至现在所l过的秒敎ͼ?Long.MIN_VALUE/1000 ?Long.MAX_VALUE/1000 之间的差倹{?/td> </tr> <tr> <td>'Q' </td> <td>自协调世界时 (UTC) 1970 q?1 ?1 ?00:00:00 至现在所l过的毫U数Q即 Long.MIN_VALUE ?Long.MAX_VALUE 之间的差倹{?/td> </tr> </tbody> </table> <br /> 以下转换字符用来格式化日期:(x) <br /> <br /> <table align="center" cellspacing="0"> <tbody> <tr> <td>'B' </td> <td>特定于语a环境?a target="_blank">月䆾全称</a>Q例?"January" ?"February"?/td> </tr> <tr> <td>'b' </td> <td>特定于语a环境?a target="_blank">月䆾U?/a>Q例?"Jan" ?"Feb"?/td> </tr> <tr> <td>'h' </td> <td>?'b' 相同?/td> </tr> <tr> <td>'A' </td> <td>特定于语a环境?a target="_blank">星期?/a>全称Q例?"Sunday" ?"Monday"</td> </tr> <tr> <td>'a' </td> <td>特定于语a环境?a target="_blank">星期?/a>Uͼ例如 "Sun" ?"Mon"</td> </tr> <tr> <td>'C' </td> <td>除以 100 的四位数表示的年份,被格式化为必要时带前导零的两位数Q即 00 - 99</td> </tr> <tr> <td>'Y' </td> <td>q䆾Q被格式化ؓ(f)必要时带前导零的四位敎ͼ臛_Q,例如Q?092 {于格里高利历的 92 CE?/td> </tr> <tr> <td>'y' </td> <td>q䆾的最后两位数Q被格式化ؓ(f)必要时带前导零的两位敎ͼ?00 - 99?/td> </tr> <tr> <td>'j' </td> <td>一q中的天敎ͼ被格式化为必要时带前导零的三位数Q例如,对于格里高利历是 001 - 366?/td> </tr> <tr> <td>'m' </td> <td>月䆾Q被格式化ؓ(f)必要时带前导零的两位敎ͼ?01 - 13?/td> </tr> <tr> <td>'d' </td> <td>一个月中的天数Q被格式化ؓ(f)必要时带前导零两位数Q即 01 - 31</td> </tr> <tr> <td>'e' </td> <td>一个月中的天数Q被格式化ؓ(f)两位敎ͼ?1 - 31?/td> </tr> </tbody> </table> <br /> 以下转换字符用于格式化常见的日期/旉l合?<br /> <br /> <table align="center" cellspacing="0"> <tbody> <tr> <td>'R' </td> <td>24 时制的旉Q被格式化ؓ(f) "%tH:%tM"</td> </tr> <tr> <td>'T' </td> <td>24 时制的旉Q被格式化ؓ(f) "%tH:%tM:%tS"?/td> </tr> <tr> <td>'r' </td> <td>12 时制的旉Q被格式化ؓ(f) "%tI:%tM:%tS %Tp"。上午或下午标记 ('%Tp') 的位|可能与语言环境有关?/td> </tr> <tr> <td>'D' </td> <td>日期Q被格式化ؓ(f) "%tm/%td/%ty"?/td> </tr> <tr> <td>'F' </td> <td><a target="_blank">ISO 8601</a> 格式的完整日期,被格式化?"%tY-%tm-%td"?/td> </tr> <tr> <td>'c' </td> <td>日期和时_(d)被格式化?"%ta %tb %td %tT %tZ %tY"Q例?"Sun Jul 20 16:17:00 EDT 1969"?/td> </tr> </tbody> </table> <br /> M未明定义ؓ(f)转换的字W都是非法字W,q且都被保留Q以供将来扩展用?br /> <br /> <font size="4"><strong><br /> 标志</strong></font><br /> 下表ȝ?jin)受支持的标志。y 表示该标志受指示参数cd支持?<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    </td> <td>y    </td> <td>y    </td> <td>y    </td> <td>y</td> <td>l果是左对齐的?/td> </tr> <tr> <td>'#'</td> <td>y1    </td> <td>-    </td> <td>y3    </td> <td>y    </td> <td>-    </td> <td>l果应该使用依赖于{换类型的替换形式</td> </tr> <tr> <td>'+'</td> <td>-    </td> <td>-    </td> <td>y4    </td> <td>y    </td> <td>-    </td> <td>l果L包括一个符?/td> </tr> <tr> <td>'   '</td> <td>-    </td> <td>-    </td> <td>y4    </td> <td>y    </td> <td>-    </td> <td>对于正|l果中将包括一个前导空?/td> </tr> <tr> <td>'0'</td> <td>-    </td> <td>-    </td> <td>y    </td> <td>y    </td> <td>-    </td> <td>l果用零来填充</td> </tr> <tr> <td>','</td> <td>-    </td> <td>-    </td> <td>y2    </td> <td>y5    </td> <td>-    </td> <td>l果包括特定于语言环境?a target="_blank">l分隔符</a></td> </tr> <tr> <td>'('</td> <td>-    </td> <td>-    </td> <td>y4    </td> <td>y5    </td> <td>-    </td> <td>l果是用圆括号括v来的负数</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 /> M未显式定义ؓ(f)标志的字W都是非法字W,q且都被保留Q以供扩展用?<br /> <br /> 宽度   宽度是将向输Z写入的最字W数。对于行分隔W{换,不适用宽度Q如果提供宽度,则会(x)抛出异常?br /> _ֺ   对于常规参数cdQ精度是向输出中写入的最多字W数?br /> 对于点转换 'e'?E' ?'f'Q精度是数点分隔符后的位数。如果{换是 'g' ?'G'Q那么精度是舍入计算后所得数值的所有位数。如果{换是 'a' ?'A'Q则不必指定_ֺ?br /> 对于字符、整数和日期/旉参数cd转换Q以?qing)百分比和行分隔W{换,_ֺ是不适用的;如果提供_ֺQ则?x)抛出异常?br /> 参数索引   参数索引是一个十q制整数Q用于表明参数在参数列表中的位置。第一个参数由 "1$" 引用Q第二个参数?"2$" 引用Q依此类推?br /> Ҏ(gu)位置引用参数的另一U方法是使用 '<' ('"u003c') 标志Q这会(x)重用以前格式说明W的参数。例如,以下两条语句产生的字W相同:(x) <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 %<$te,%<$tY", c);</blockquote> <img src ="http://www.tkk7.com/java-blog/aggbug/189040.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-03-27 16:09 <a href="http://www.tkk7.com/java-blog/articles/189040.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4j配置http://www.tkk7.com/java-blog/articles/180369.html一步一步努力向上爬一步一步努力向上爬Sun, 17 Feb 2008 15:51:00 GMThttp://www.tkk7.com/java-blog/articles/180369.htmlhttp://www.tkk7.com/java-blog/comments/180369.htmlhttp://www.tkk7.com/java-blog/articles/180369.html#Feedback0http://www.tkk7.com/java-blog/comments/commentRss/180369.htmlhttp://www.tkk7.com/java-blog/services/trackbacks/180369.html一.参数意义说明
输出U别的种c?
ERROR、WARN、INFO、DEBUG
ERROR Z重错?主要是程序的错误
WARN Z般警告,比如session丢失
INFO Z般要昄的信息,比如dd
DEBUG 为程序的调试信息
配置日志信息输出目的?
log4j.appender.appenderName = fully.qualified.name.of.appender.class
1.org.apache.log4j.ConsoleAppenderQ控制台Q?
2.org.apache.log4j.FileAppenderQ文Ӟ(j)
3.org.apache.log4j.DailyRollingFileAppenderQ每天生一个日志文Ӟ(j)
4.org.apache.log4j.RollingFileAppenderQ文件大到达指定尺寸的时候生一个新的文Ӟ(j)
5.org.apache.log4j.WriterAppenderQ将日志信息以流格式发送到L指定的地方)(j)
­
配置日志信息的格?
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
1.org.apache.log4j.HTMLLayoutQ以HTML表格形式布局Q,
2.org.apache.log4j.PatternLayoutQ可以灵zd指定布局模式Q,
3.org.apache.log4j.SimpleLayoutQ包含日志信息的U别和信息字W串Q,
4.org.apache.log4j.TTCCLayoutQ包含日志生的旉、线E、类别等{信息)(j)
控制台选项
Threshold=DEBUG:指定日志消息的输出最低层ơ?
ImmediateFlush=true:默认值是true,意谓着所有的消息都会(x)被立卌出?
Target=System.errQ默认情况下是:(x)System.out,指定输出控制?
FileAppender 选项
Threshold=DEBUF:指定日志消息的输出最低层ơ?
ImmediateFlush=true:默认值是true,意谓着所有的消息都会(x)被立卌出?
File=mylog.txt:指定消息输出到mylog.txt文g?
Append=false:默认值是true,卛_消息增加到指定文件中Qfalse指将消息覆盖指定的文件内宏V?
RollingFileAppender 选项
Threshold=DEBUG:指定日志消息的输出最低层ơ?
ImmediateFlush=true:默认值是true,意谓着所有的消息都会(x)被立卌出?
File=mylog.txt:指定消息输出到mylog.txt文g?
Append=false:默认值是true,卛_消息增加到指定文件中Qfalse指将消息覆盖指定的文件内宏V?
MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小Ӟ会(x)自动滚动Q即原来的内容Udmylog.log.1文g?
MaxBackupIndex=2:指定可以产生的滚动文件的最大数?
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
日志信息格式中几个符h代表的含义:(x)
-X? X信息输出时左寚wQ?
%p: 输出日志信息优先U,即DEBUGQINFOQW(xu)ARNQERRORQFATAL,
%d: 输出日志旉点的日期或时_(d)默认格式为ISO8601Q也可以在其后指定格式,比如Q?d{yyy MMM dd HH:mm:ss,SSS}Q输出类|(x)2002q?0?8?22Q?0Q?8Q?21
%r: 输出自应用启动到输出该log信息耗费的毫U数
%c: 输出日志信息所属的cȝQ通常是所在类的全?
%t: 输出产生该日志事件的U程?
%l: 输出日志事g的发生位|,相当?C.%M(%F:%L)的组?包括cȝ名、发生的U程Q以?qing)在代码中的行数。D例:(x)Testlog4.main (TestLog4.java:10)
%x: 输出和当前线E相兌的NDC(嵌套诊断环境),其用到像java servletsq样的多客户多线E的应用中?
%%: 输出一?%"字符
%F: 输出日志消息产生时所在的文g名称
%L: 输出代码中的行号
%m: 输出代码中指定的消息,产生的日志具体信?
%n: 输出一个回车换行符QW(xu)indowsq_?"r"n"QUnixq_?"n"输出日志信息换行
可以?与模式字W之间加上修饰符来控制其最宽度、最大宽度、和文本的对齐方式。如Q?
1)%20cQ指定输出category的名Uͼ最的宽度?0Q如果category的名U小?0的话Q默认的情况下右寚w?
2)%-20c:指定输出category的名Uͼ最的宽度?0Q如果category的名U小?0的话Q?-"h定左寚w?
3)%.30c:指定输出category的名Uͼ最大的宽度?0Q如果category的名U大?0的话Q就?x)将左边多出的字W截掉,但小?0的话也不?x)有I格?
4)%20.30c:如果category的名U小?0pI格Qƈ且右寚wQ如果其名称长于30字符Q就从左边较q输出的字符截掉?
?文g配置Sample1
log4j.rootLogger=DEBUG,A1,R
#log4j.rootLogger=INFO,A1,R
# ConsoleAppender 输出
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n
# File 输出 一天一个文?输出路径可以定制,一般在根\径下
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=blog_log.txt
log4j.appender.R.MaxFileSize=500KB
log4j.appender.R.MaxBackupIndex=10
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n
文g配置Sample2
下面l出的Log4J配置文g实现?jin)输出到控制収ͼ文gQ回滚文Ӟ发送日志邮Ӟ输出到数据库日志表,自定义标{全套功能?
log4j.rootLogger=DEBUG,CONSOLE,A1,im
#DEBUG,CONSOLE,FILE,ROLLING_FILE,MAIL,DATABASE
log4j.addivity.org.apache=true
­
###################
# Console Appender
###################
log4j.appender.C.apache.log4j.ConsoleAppender
log4j.appender.Threshold=DEBUG
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
#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
­
#####################
# File Appender
#####################
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=file.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
# Use this layout for LogFactor 5 analysis
­
########################
# Rolling File
########################
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log
log4j.appender.ROLLING_FILE.Append=true
log4j.appender.ROLLING_FILE.MaxFileSize=10KB
log4j.appender.ROLLING_FILE.MaxBackupIndex=1
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
­
####################
# Socket Appender
####################
log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=5001
log4j.appender.SOCKET.Locati
# Set up for Log Facter 5
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
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
­
########################
# Log Factor 5 Appender
########################
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
­
########################
# SMTP Appender
#######################
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.SMTPHost=mail.hollycrm.com
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
­
########################
# JDBC Appender
#######################
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
­
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout
###################
#自定义Appender
###################
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = corlin@cybercorlin.net
log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
­
?高使用
实验目的Q?
1.把FATALU错误写?000NT日志
2. WARNQERRORQFATALU错误发送email通知理?
3.其他U别的错误直接在后台输出
­
实验步骤Q?
输出?000NT日志
1.把Log4j压羃包里的NTEventLogAppender.dll拷到WINNT"SYSTEM32目录?
2.写配|文件log4j.properties
# ?000pȝ日志输出
log4j.logger.NTlog=FATAL, A8
# APPENDER A8
log4j.appender.A8=org.apache.log4j.nt.NTEventLogAppender
log4j.appender.A8.Source=JavaTest
log4j.appender.A8.layout=org.apache.log4j.PatternLayout
log4j.appender.A8.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
3.调用代码Q?
Logger logger2 = Logger.getLogger("NTlog"); //要和配置文g中设|的名字相同
logger2.debug("debug!!!");
logger2.info("info!!!");
logger2.warn("warn!!!");
logger2.error("error!!!");
//只有q个错误才会(x)写入2000日志
logger2.fatal("fatal!!!");
­
发送email通知理员:(x)
1. 首先下蝲JavaMail和JAF,
在项目中引用mail.jar和activation.jar?
2. 写配|文?
# 日志发送到email
log4j.logger.MailLog=WARN,A5
#  APPENDER A5
log4j.appender.A5=org.apache.log4j.net.SMTPAppender
log4j.appender.A5.BufferSize=5
log4j.appender.A5.Subject=ErrorLog
log4j.appender.A5.SMTPHost=smtp.263.net
log4j.appender.A5.layout=org.apache.log4j.PatternLayout
log4j.appender.A5.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
3.调用代码Q?
//把日志发送到mail
Logger logger3 = Logger.getLogger("MailLog");
logger3.warn("warn!!!");
logger3.error("error!!!");
logger3.fatal("fatal!!!");
在后台输出所有类别的错误Q?
1. 写配|文?
# 在后台输?
log4j.logger.c, A1
# APPENDER A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
2Q调用代?
Logger logger1 = Logger.getLogger("console");
logger1.debug("debug!!!");
logger1.info("info!!!");
logger1.warn("warn!!!");
logger1.error("error!!!");
logger1.fatal("fatal!!!");
--------------------------------------------------------------------
全部配置文gQlog4j.properties
# 在后台输?
log4j.logger.c, A1
# APPENDER A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
# ?000pȝ日志输出
log4j.logger.NTlog=FATAL, A8
# APPENDER A8
log4j.appender.A8=org.apache.log4j.nt.NTEventLogAppender
log4j.appender.A8.Source=JavaTest
log4j.appender.A8.layout=org.apache.log4j.PatternLayout
log4j.appender.A8.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
# 日志发送到email
log4j.logger.MailLog=WARN,A5
#  APPENDER A5
log4j.appender.A5=org.apache.log4j.net.SMTPAppender
log4j.appender.A5.BufferSize=5
log4j.appender.A5.Subject=ErrorLog
log4j.appender.A5.SMTPHost=smtp.263.net
log4j.appender.A5.layout=org.apache.log4j.PatternLayout
log4j.appender.A5.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
全部代码QLog4jTest.java
  
/*
  * 创徏日期 2003-11-13
  */
package edu.bcu.Bean;
import org.apache.log4j.*;
//import org.apache.log4j.nt.*;
//import org.apache.log4j.net.*;
/**
  * @author yanxu
  */
public class Log4jTest
{
  public static void main(String args[])
  {
   PropertyConfigurator.configure("log4j.properties");
   //在后台输?
   Logger logger1 = Logger.getLogger("console");
   logger1.debug("debug!!!");
   logger1.info("info!!!");
   logger1.warn("warn!!!");
   logger1.error("error!!!");
   logger1.fatal("fatal!!!");
   //在NTpȝ日志输出
   Logger logger2 = Logger.getLogger("NTlog");
   //NTEventLogAppender nla = new NTEventLogAppender();
   logger2.debug("debug!!!");
   logger2.info("info!!!");
   logger2.warn("warn!!!");
   logger2.error("error!!!");
   //只有q个错误才会(x)写入2000日志
   logger2.fatal("fatal!!!");
   //把日志发送到mail
   Logger logger3 = Logger.getLogger("MailLog");
   //SMTPAppender sa = new SMTPAppender();
   logger3.warn("warn!!!");
   logger3.error("error!!!");
   logger3.fatal("fatal!!!");
  }
}
 

]]>
JDK5 U程?http://www.tkk7.com/java-blog/articles/176225.html一步一步努力向上爬一步一步努力向上爬Fri, 18 Jan 2008 07:18:00 GMThttp://www.tkk7.com/java-blog/articles/176225.htmlhttp://www.tkk7.com/java-blog/comments/176225.htmlhttp://www.tkk7.com/java-blog/articles/176225.html#Feedback0http://www.tkk7.com/java-blog/comments/commentRss/176225.htmlhttp://www.tkk7.com/java-blog/services/trackbacks/176225.html   希望大家多提意见。指出哪里写的不好,以后加以Ҏ(gu)?br />
ThreadPoolManagerc:(x)负责理U程池,调用轮询的线E来讉K字符串缓冲区的内容,l护~冲区,当线E池溢出时抛出的Runnabled被加入到字符~冲区?br /> public class ThreadPoolManager
{
    private static ThreadPoolManager tpm = new ThreadPoolManager();

    // U程池维护线E的最数?br />     private final static int CORE_POOL_SIZE = 4;

    // U程池维护线E的最大数?br />     private final static int MAX_POOL_SIZE = 10;

    // U程池维护线E所允许的空闲时?br />     private final static int KEEP_ALIVE_TIME = 0;

    // U程池所使用的缓冲队列大?br />     private final static int WORK_QUEUE_SIZE = 10;

    // 消息~冲队列
    Queue<String> msgQueue = new LinkedList<String>();

    // 讉K消息~存的调度线E?br />     final Runnable accessBufferThread = new Runnable()
    {
        public void run()
        {
            // 查看是否有待定请求,如果有,则创Z个新的AccessDBThreadQƈd到线E池?br />             if( hasMoreAcquire() )
            {
                String msg = ( String ) msgQueue.poll();
                Runnable task = new AccessDBThread( msg );
                threadPool.execute( task );
            }
        }
    };

    final RejectedExecutionHandler handler = new RejectedExecutionHandler()
    {
        public void rejectedExecution( Runnable r, ThreadPoolExecutor executor )
        {
            System.out.println(((AccessDBThread )r).getMsg()+"消息攑օ队列中重新等待执?);
            msgQueue.offer((( AccessDBThread ) r ).getMsg() );
        }
    };

    // 理数据库访问的U程?br />     final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
            new ArrayBlockingQueue( WORK_QUEUE_SIZE ), this.handler );

    // 调度U程?br />     final ScheduledExecutorService scheduler = Executors
            .newScheduledThreadPool( 1 );

    final ScheduledFuture taskHandler = scheduler.scheduleAtFixedRate(
            accessBufferThread, 0, 1, TimeUnit.SECONDS );

    public static ThreadPoolManager newInstance()
    {
        return tpm;
    }

    private ThreadPoolManager(){}

    private boolean hasMoreAcquire()
    {
        return !msgQueue.isEmpty();
    }

    public void addLogMsg( String msg )
    {
        Runnable task = new AccessDBThread( msg );
        threadPool.execute( task );
    }
}

public class AccessDBThread implements Runnable
{
    private String msg;
    
    public String getMsg()
    {
        return msg;
    }

    public void setMsg( String msg )
    {
        this.msg = msg;
    }
    
    public AccessDBThread(){
        super();
    }
    
    public AccessDBThread(String msg){
        this.msg = msg;
    }

    public void run()
    {
        // 向数据库中添加Msg变量?br />         System.out.println("Added the message: "+msg+" into the Database");
    }

}

public class TestDriver
{
    ThreadPoolManager tpm = ThreadPoolManager.newInstance();

    public void sendMsg( String msg )
    {
        tpm.addLogMsg( msg + "记录一条日?nbsp;" );
    }

    public static void main( String[] args )
    {
        for( int i = 0; i < 100; i++ )
        {
            new TestDriver().sendMsg( Integer.toString( i ) );
        }
    }
}

]]>
JDK5 U程?/title><link>http://www.tkk7.com/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.tkk7.com/java-blog/articles/176222.html</guid><wfw:comment>http://www.tkk7.com/java-blog/comments/176222.html</wfw:comment><comments>http://www.tkk7.com/java-blog/articles/176222.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/java-blog/comments/commentRss/176222.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/java-blog/services/trackbacks/176222.html</trackback:ping><description><![CDATA[Java5增加?jin)新的类库ƈ发集java.util.concurrentQ该cd为ƈ发程序提供了(jin)丰富的API多线E编E在Java 5中更加容易,灉|。本文通过一个网l服务器模型Q来实践Java5的多U程~程Q该模型中用了(jin)Java5中的U程池,d队列Q可重入锁等Q还实践? CallableQ?Future{接口,q用了(jin)Java 5的另外一个新Ҏ(gu)泛型?br /> <br /> ?<br /> <br /> 本文实C个网l服务器模型Q一旦有客户端连接到该服务器Q则启动一个新U程q接服务Q服务内容ؓ(f)往客户端输送一些字W信息。一个典型的|络服务器模型如下:(x)<br /> <br /> 1. 建立监听端口?br /> <br /> 2. 发现有新q接Q接受连接,启动U程Q执行服务线E?3. 服务完毕Q关闭线E?br /> <br /> q个模型在大部分情况下运行良好,但是需要频J的处理用户h而每ơ请求需要的服务又是短的时候,pȝ?x)将大量的时间花费在U程的创建销毁。Java 5的线E池克服?jin)这些缺炏V通过寚w用线E来执行多个dQ避免了(jin)频繁U程的创Z销毁开销Q得服务器的性能斚w得到很大提高。因此,本文的网l服务器 模型如下:(x)<br /> <br /> 1. 建立监听端口Q创建线E池?br /> <br /> 2. 发现有新q接Q用线E池来执行服务Q务?br /> <br /> 3. 服务完毕Q释攄E到U程池?br /> <br /> 下面详细介绍如何使用Java 5的concurrent包提供的API来实现该服务器?br /> <br /> 初始?br /> <br /> 初始化包括创建线E池以及(qing)初始化监听端口。创建线E池可以通过调用java.util.concurrent.Executorsc里的静(rn)态方? newChahedThreadPool或是newFixedThreadPool来创建,也可以通过新徏一? java.util.concurrent.ThreadPoolExecutor实例来执行Q务。这里我们采用newFixedThreadPool? 法来建立U程池?br /> <br /> ExecutorService pool = Executors.newFixedThreadPool(10); <br /> <br /> 表示新徏?jin)一个线E池Q线E池里面?0个线Eؓ(f)d队列服务?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 /> 当有新连接徏立时Qacceptq回Ӟ服务Q务提交给U程池执行?br /> <br /> while(true){<br /> Socket socket = serverListenSocket.accept();<br /> pool.execute(new ServiceThread(socket));<br /> } <br /> <br /> q里使用U程池对象来执行U程Q减了(jin)每次U程创徏和销毁的开销。Q务执行完毕,U程释放到线E池?br /> <br /> 服务d<br /> <br /> 服务U程ServiceThreadl护一个count来记录服务线E被调用的次数。每当服务Q务被调用一ơ时Qcount的D?Q因? ServiceThread提供一个increaseCount和getCount的方法,分别countD?和取得该count倹{由于可能多? U程存在竞争Q同时访问countQ因此需要加锁机Ӟ在Java 5之前Q我们只能用synchronized来锁定。Java 5中引入了(jin)性能更加_度更细的重入锁ReentrantLock。我们用ReentrantLock保证代码U程安全。下面是具体代码Q?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 /> 服务U程在开始给客户端打C个欢q信息,<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Ҏ(gu)提交一个Callable的Q务,q回一个Future接口的引用。这U做法对Ҏ(gu)的Q务非 常有效,submitd之后可以l箋(hu)执行下面的代码,然后在适当的位|可以用Future的getҎ(gu)来获取结果,如果q时候该Ҏ(gu)已经执行完毕Q则 无需{待卛_获得l果Q如果还在执行,则等待到q行完毕?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实现?jin)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 /> q里使用?jin)Java 5的另外一个新Ҏ(gu)泛型,声明TimeConsumingTask的时候用了(jin)String做ؓ(f)cd参数。必d现Callable接口的call函数Q? 其作用类gRunnable中的run函数Q在call函数里写入要执行的代码,其返回值类型等同于在类声明中传入的cd倹{在q段E序中,我们提交? 一个Callable的Q务,然后E序不会(x)堵塞Q而是l箋(hu)执行dos.write("let's do soemthing other".getBytes());当程序执行到String result = future.get()时如果call函数已经执行完毕Q则取得q回|如果q在执行Q则{待其执行完毕? <img src ="http://www.tkk7.com/java-blog/aggbug/176222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/java-blog/" target="_blank">一步一步努力向上爬</a> 2008-01-18 15:16 <a href="http://www.tkk7.com/java-blog/articles/176222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转:(x)一个bit操作的类 http://www.tkk7.com/java-blog/articles/169119.html一步一步努力向上爬一步一步努力向上爬Thu, 20 Dec 2007 10:18:00 GMThttp://www.tkk7.com/java-blog/articles/169119.htmlhttp://www.tkk7.com/java-blog/comments/169119.htmlhttp://www.tkk7.com/java-blog/articles/169119.html#Feedback0http://www.tkk7.com/java-blog/comments/commentRss/169119.htmlhttp://www.tkk7.com/java-blog/services/trackbacks/169119.html    不知道有没有更好的方法,拿出来让大家看看吧!

源代码:(x)

/**
 * @author 沈东?Edward Shen<a href="mailto:shendl_s@hotmail.com">shendl_s@hotmail.com</a>
 * 2007-5-23 下午03:11:45
 *执行位操?br />  *
 *
 */
public class BitUtil {
 /**
  * 把字节指定的位数设ؓ(f)1Q不原来该位是什么?br />   * @param data
  * @param pos  ?开?br />   */
 public static byte setByteBitOne(byte data,int pos){
  byte compare=(byte) Math.pow(2.0,pos);
  data=(byte) (data|compare);
  return data;
 }
 /**
  * 把字节指定的位数设ؓ(f)0Q不原来该位是什么?br />   * @param data
  * @param pos
  */
 public static byte setByteBitZero(byte data,int pos){
  byte compare=(byte) ~(byte) Math.pow(2.0,pos);
  data=(byte) (data&compare);
  return data;
 }
 
 
 
    /**
     * q回指定字节W几个位的数字,只可能是Q或者1
     * @param data
     * @param pos   ?开始的位数
     * @return
     */
 public static int getByteBit(byte data,int pos){
  int bitData = 0;
  
  byte compare=(byte) Math.pow(2.0,pos);
  if((data & compare)==compare){
   bitData =1;
   
  }
  
  
  
  return bitData;
 
 }
 /**
  * q回一个字节的每一位的数字
  * @param data
  * @return
  */
 public static byte[] getByteBits(byte data){
  byte[] results=new byte[8];
  for(int i=0;i<8;i++){
   results[i]=(byte) BitUtil.getByteBit(data, i);
   
  }
  
   
  
  
  
  return results;
 }

 /**
  *
  */
 public BitUtil() {
  /*
   *
   */
 }

 }
 



]]>
使用临时变量提高Java代码性能 (?http://www.tkk7.com/java-blog/articles/158871.html一步一步努力向上爬一步一步努力向上爬Wed, 07 Nov 2007 09:18:00 GMThttp://www.tkk7.com/java-blog/articles/158871.htmlhttp://www.tkk7.com/java-blog/comments/158871.htmlhttp://www.tkk7.com/java-blog/articles/158871.html#Feedback0http://www.tkk7.com/java-blog/comments/commentRss/158871.htmlhttp://www.tkk7.com/java-blog/services/trackbacks/158871.htmlauthor: ZJ 2007-11-6
 
一个JavacM可以存在多种形式的变量,可以是最一般的成员变量Q或其定义为静(rn)态变量;也可以在Ҏ(gu)中定义(f)时变量。这三种变量的存取效率如何?
1Q测?/span>
下面作个实验Q看下面代码?/font>
class CheckVars {
    privateintinstVar;// 成员变量
    privatestaticintstaticVar; // ?rn)态变?/span>
 
    // 存取cL法中的(f)时变?/span>
    void tempAccess(int val) {
       int j = 0;// 临时变量
       long startTime = System.currentTimeMillis();
       for (int i = 0; i < val; i++)
           j += 1;
       long endTime = System.currentTimeMillis();
       System.out.println("temp var: " + (endTime - startTime) + " milli seconds");
    }
 
    // 存取cȝ成员变量
    void instanceAccess(int val) {
       long startTime = System.currentTimeMillis();
       for (int i = 0; i < val; i++)
           instVar += 1;
       long endTime = System.currentTimeMillis();
       System.out.println("instance var: " + (endTime - startTime) + " milli seconds");
    }
 
    // 存取cȝ static 变量
    void staticAccess(int val) {
       long startTime = System.currentTimeMillis();
       for (int i = 0; i < val; i++)
           staticVar += 1;
       long endTime = System.currentTimeMillis();
       System.out.println("static var: " + (endTime - startTime) + " milli seconds");
    }
   
    publicstaticvoid main(String[] args){
       CheckVars test=new CheckVars();
       test.tempAccess(200000000);
       test.instanceAccess(200000000);
       test.staticAccess(200000000);
    }
}
 
l果Q?/span>
temp var: 350 milli seconds
instance var: 821 milli seconds
static var: 852 milli seconds
 
q段代码中的每个Ҏ(gu)都执行相同的循环Q?/span>q反复相同的ơ数。唯一的不同是每个循环使一个不同类型的变量递增。方?/span> tempAccess 使一个局部堆栈变量递增Q?/span>instanceAccess 使类的一个成员实例变量递增Q?/span> staticAccess 使类的一?/span> static 变量递增?/span>
从结果中可以发现Q?/span>instanceAccess ?/span> staticAccess 的执行时间基本相同。但是,tempAccess 要快两到三倍?/span>
 
2Q?/span>JVM存取变量机制
存取堆栈变量如此快是因ؓ(f)JVM 存取堆栈变量比它存取 static 变量或类的实例变量执行的操作?/span>
JVM 是一U基于堆栈的虚拟机,因此优化?jin)对堆栈数据的存取和处理。所有局部变量都存储在一个局部变量表中,?/span> Java 操作数堆栈中q行处理Qƈ可被高效地存取?/span>
存取 static 变量和实例变量成本更高,因ؓ(f) JVM 必须使用代h(hun)更高的操作码Qƈ从常数存储池中存取它们。(常数存储池保存(sh)个类型所使用的所有类型、字D和Ҏ(gu)的符号引用。)(j)通常Q在W一ơ从常数存储池中讉K static 变量或实例变量以后,JVM 动态更改字节码以用效率更高的操作码。尽有q种优化Q堆栈变量的存取仍然更快?/span>
 
3Q优化代?/span>
考虑到这些事实,可以重新构建前面的代码Q以侉K过存取堆栈变量而不是实例变量或 static 变量使操作更高效?/span>
publicclass CheckVarsAdv {
    privateintinstVar;
    privatestaticintstaticVar;
 
    void tempAccess(int val) {
       int j = 0;
       long startTime = System.currentTimeMillis();
       for (int i = 0; i < val; i++)
           j += 1;
       long endTime = System.currentTimeMillis();
       System.out.println("temp var: " + (endTime - startTime) + " milli seconds");
    }
 
    void instanceAccess(int val) {
       int j = instVar;
       long startTime = System.currentTimeMillis();
       for (int i = 0; i < val; i++)
           j += 1;
       long endTime = System.currentTimeMillis();
       System.out.println("instance var: " + (endTime - startTime) + " milli seconds");
       instVar = j;
    }
 
    void staticAccess(int val) {
       int j = staticVar;
       long startTime = System.currentTimeMillis();
       for (int i = 0; i < val; i++)
           j += 1;
       long endTime = System.currentTimeMillis();
       System.out.println("static var: " + (endTime - startTime) + " milli seconds");
       staticVar = j;
    }
   
    publicstaticvoid main(String[] args){
       CheckVarsAdv test=new CheckVarsAdv();
       test.tempAccess(200000000);
       test.instanceAccess(200000000);
       test.staticAccess(200000000);
    }
}
 
l果Q?/font>
temp var: 341 milli seconds
instance var: 370 milli seconds
static var: 361 milli seconds
 
Ҏ(gu) instanceAccess ?/span> staticAccess 被修改ؓ(f)它们的实例变量?/span> static 变量复制到局部堆栈变量中。当变量的处理完成以后,其值又被复制回实例变量?/span> static 变量中。这U简单的更改明显提高?sh)?/span> instanceAccess ?/span> staticAccess 的性能。这三个Ҏ(gu)的执行时间现在基本相同?/span>

本文?gu)?“??/a>” 博客Q请务必保留此出?a >http://zhangjunhd.blog.51cto.com/113473/49322



]]>
~写跨^台JavaE序的几个要?/title><link>http://www.tkk7.com/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.tkk7.com/java-blog/articles/156698.html</guid><wfw:comment>http://www.tkk7.com/java-blog/comments/156698.html</wfw:comment><comments>http://www.tkk7.com/java-blog/articles/156698.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/java-blog/comments/commentRss/156698.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/java-blog/services/trackbacks/156698.html</trackback:ping><description><![CDATA[<h2><a >~写跨^台JavaE序的几个要?/a></h2> Submitted by <a title="查看用户信息?>robertb9527</a> on 八月 8, 2004 - 12:50. <ul inline=""> <li last="" taxonomy_term_1=""><a rel="tag" title="老康的Program" class="taxonomy_term_1">Program</a></li> </ul> <div> <p>用Java~写E序最大的优点在于“一ơ编译,处处q行”Q可是事实上Q相当一部分的JavaE序不能在别的操作系l上正确q行Q最后倒搞成了(jin)“一ơ编写,处处调试”Q那么如何才能编写一个真正的跨^台的JavaE序呢?下面有几个要点要注意Q?</p> <p>  1.你的E序需要是100%UJava的。特别是使用W三方的cd包时一定要注意q一炏V?</p> <p>  2.无论你用的是JDK或其他开发工P在编译时都要打开所有的警告选项Q这L(fng)译器可以可能多的发现^台相关的语句Qƈl出警告。虽然不能保证没有编译时警告的程序一定是跨^台的Q但含有警告的程序却很有可能是非q_无关的?</p> <p>  3.׃JDK是向下兼容的Q因此可以用过时的Ҏ(gu)QDeprecated methodQ,但调试时要打开Qdeprecation选项?/p> <p> 4.退出JavaE序时尽量不要用java.lang.System的exitҎ(gu)。Exit Ҏ(gu)可以l止JVMQ从而终止程序,但如果同时运行了(jin)另一个JavaE序Q用exitҎ(gu)׃(x)让该E序也关闭,q显然不是我们希望看到的情况。事实上? 退出JavaE序Q可以用destory()退Z个独立运行的U程。对于多U程E序Q必要关闭各个非守护线E。只有在E序非正帔R出时Q才使用 exitҎ(gu)退出程序?</p> <p>  5.避免使用本地Ҏ(gu)和本C码,可能自q写具有相应功能的Javac,改写该方法。如果一定要使用该本地方法,可以~写一个服务器E序调用该方法,然后现在要~写的程序作服务器程序的客户E序Q或者考虑CORBAQ公共对象请求代理)(j)E序l构?</p> <p> 6.Java中有一个类gDelphi中的winexec的方法,java.lang.runtimecȝexecҎ(gu)Q作Ҏ(gu)本n是具有^台无 x(chng)的Q但是给Ҏ(gu)所调用的命令及(qing)命o(h)参数却是与^台相关的Q因此,在编写程序时要避免用,如果一定要调用其他的程序的话,必须要让用户自己来设|该? 令及(qing)其参数。比如说Q在windows中可以调用notepad.exeE序Q在linux 中就要调用viE序?jin)?</p> <p>  7.注意q不是所有的操作pȝ都支持Unicode字符集,q对于跨q_的Java中文软gE序不能不说是一大噩耗?</p> <p> 8.在程序中不要性编码与q_相关的Q何常量,比如行分隔符Q文件分隔符Q\径分隔符{等Q这些常量在不同的^C是不同的Q比如文件分隔符Q在 UNIX和MAC中是“/”Q在windows中是“"”Q如果要使用q些帔RQ需要用jdava.util.Propertiescȝ getPropertyҎ(gu)Q如java.util.Properties.getProperty(“file.separator”)可以获得文g? 隔符QgetProperty (“line.separator”)q回行分隔符QgetProperty(“path.separator”)q回路径分隔W?</p> <p> 9.在编写跨q_的网l程序时Q不要用java.net.InetAddresscȝgetHostNameҎ(gu)得到L名,因ؓ(f)不同的^台的L? 格式是不同的Q最好用getAddress得到格式相同的IP地址Q另外,E序中所有的L名都要换成IP地址Q比如www.b9527.netp? 成相应的IP地址?</p> <p>  10.涉及(qing)文g操作的程序需要注意:(x)不要在程序中性编码文件\径,而且不同q_对于文g名用的字符?qing)最大文件名长度的要求不同,~写你的E序的时候要使用一般的ASCII码字W作为文件的名字Q而且不能与^C已存在的E序同名Q否则会(x)造成冲突?</p> <p>  11.如果你写的程序是GUIE序Q在使用AWTlg时不要硬性设|组件的大小和位|而应该用Java的布局理器来讄和管理可视组件的大小和位|,否则有可能造成布局混ؕ?</p> <p> 12.׃不同的操作系l,不同的机器,pȝ支持的颜色和屏幕的大和分L率都不同Q如何获得这些属性呢Q? java.awt.Systemcolorcd以获得需要的颜色Q如该类的inactiveCaption 是H口Ҏ(gu)中活动标题的背景颜色Qmenu则是菜单的背景颜艌Ӏ用java.awt.Toolkit的getScreenResolution可以? “像素每英?#8221;为单位显C屏q的分L率。该cȝgetScreenSize可以得到屏幕大小(英寸)QloadSystemColors可以列出所有的p? l颜艌Ӏ?/p> </div> <img src ="http://www.tkk7.com/java-blog/aggbug/156698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/java-blog/" target="_blank">一步一步努力向上爬</a> 2007-10-29 15:49 <a href="http://www.tkk7.com/java-blog/articles/156698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://w6446.com" target="_blank">޾ƷƷþ99</a>| <a href="http://bznys.com" target="_blank">Ļ޾Ʒ</a>| <a href="http://onisterwines.com" target="_blank">˳߲VA</a>| <a href="http://doubaye.com" target="_blank">㽶Ƶ</a>| <a href="http://zanyoo.com" target="_blank">޹ɫƵ</a>| <a href="http://yw756.com" target="_blank">ձɫͼ߹ۿ</a>| <a href="http://144446.com" target="_blank">ҹҹAһ</a>| <a href="http://nkldj.com" target="_blank">ҳվƵ</a>| <a href="http://456qqq.com" target="_blank">ŮڵƵվ</a>| <a href="http://4466n.com" target="_blank">þþƷAVɫ</a>| <a href="http://3333seav.com" target="_blank">18ŮվɫƬѹۿ</a>| <a href="http://kph37.com" target="_blank">޳AVƬ</a>| <a href="http://czdlglass.com" target="_blank">߹ۿ</a>| <a href="http://fdsyjy.com" target="_blank">޾Ʒ߹ۿ</a>| <a href="http://4001120002.com" target="_blank">ŷۺһ</a>| <a href="http://yyfass.com" target="_blank">Ļվ</a>| <a href="http://jpvv8.com" target="_blank">޾ƷŮһ</a>| <a href="http://yyfass.com" target="_blank">A߹ۿվȫ</a>| <a href="http://eee94.com" target="_blank">޹Ʒ˾þõӰ</a>| <a href="http://166sb.com" target="_blank">ƵѲ</a>| <a href="http://thinkchating.com" target="_blank">Ƶ߿</a>| <a href="http://wwwfac286.com" target="_blank">þùɫAVѿ</a>| <a href="http://imfever.com" target="_blank">91˾Ʒϵȫ </a>| <a href="http://www-7607.com" target="_blank">Ůٸһ</a>| <a href="http://888xxss.com" target="_blank">eeussӰԺwww</a>| <a href="http://czshenyue.com" target="_blank">޹ۺϾþ</a>| <a href="http://xbooktxt.com" target="_blank">һëƬѹۿշ</a>| <a href="http://600c63.com" target="_blank">ձĻ</a>| <a href="http://ynkaishan.com" target="_blank">һ߹ۿƵ</a>| <a href="http://xxx2222.com" target="_blank">ŷպþAV </a>| <a href="http://fangdazd.com" target="_blank">þ</a>| <a href="http://51708695.com" target="_blank">þҹҹ³³Ƭ </a>| <a href="http://html5text.com" target="_blank">һֻ</a>| <a href="http://glhrsydc.com" target="_blank">ɫһۺ</a>| <a href="http://kj555888.com" target="_blank">޾ƷѶ</a>| <a href="http://yinyinai155.com" target="_blank">AV߹ۿ</a>| <a href="http://mcjc1.com" target="_blank">椸ѹۿƵ</a>| <a href="http://502274.com" target="_blank">96|</a>| <a href="http://48eh.com" target="_blank">޾Ʒ456</a>| <a href="http://cqtchtwq.com" target="_blank">Ƶ߹ۿ</a>| <a href="http://www-44334.com" target="_blank">vaþþþúݺ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>