http://kanglecjr.iteye.com/blog/1070934
java.util.concurrent 范例之一 JavaTomcatthread
java.util.concurrent 之一
Java代碼 ?
package ?test; ???? import ?java.util.concurrent.ExecutorService; ??import ?java.util.concurrent.Executors; ??public ?class ?TestThreadPool?{ ??????public ?static ?void ?main(String?args[])?throws ?InterruptedException{ ?? ?????? ????ExecutorService?exec?=?Executors.newFixedThreadPool(2 ); ?? ????for (int ?index=0 ;?index?<?10 ;?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); ?? ????}????? ????exec.shutdown(); ?? } ?? ????}?? package test;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestThreadPool {public static void main(String args[]) throws InterruptedException{// only two threadsExecutorService exec = Executors.newFixedThreadPool(2);for(int index=0; index < 10; 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 shutdownexec.shutdown();
}}
可能的運行結果:
Java代碼 ?
Sleeping?543ms ?? Sleeping?33ms ?? Sleeping?658ms ?? Sleeping?740ms ?? Sleeping?145ms ?? Sleeping?216ms ?? Sleeping?890ms ?? Sleeping?864ms ?? Sleeping?786ms ?? Sleeping?644ms?? Sleeping 543ms
Sleeping 33ms
Sleeping 658ms
Sleeping 740ms
Sleeping 145ms
Sleeping 216ms
Sleeping 890ms
Sleeping 864ms
Sleeping 786ms
Sleeping 644ms
??? 上面是一個簡單的例子。使用大小為2的線程池來處理10個線程。
它使用了Executors的靜態函數 newFixedThreadPool() 生成一個固定的線程池。顧名思義,
線程池是不會釋放的,即使它是Idle。這就會產生性能問題。比如如果線程池的大小為200,當全部使用完畢后,
所有的線程會繼續留在池中,相應的內存和線程切換(while(true)+sleep)都會增加。如果要避免這個問題,就
必須直接使用ThreadPoolExecutor()來構造。可以像Tomcat的線程池一樣,設置“最大線程數”、“最小線程數”
和“空閑線程keepAlive的時間”。通過這些可以基本上替換Tomcat的線程池實現方案。
需要注意的是線程池必須使用shutdown來顯式關閉,否則主線程就無法退出。
?
java.util.concurrent 范例之二:周期性運行
http://kanglecjr.iteye.com/blog/1071022
Java代碼 ?
package ?test; ???? 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)); ?? ????} ?? ???}; ?? ????? ???final ?ScheduledFuture?beeperHandle?=?scheduler.scheduleAtFixedRate(beeper,?1 ,?2 ,?SECONDS); ?? ??? ?? ???final ?ScheduledFuture?beeperHandle2?=?scheduler.scheduleWithFixedDelay(beeper,?2 ,?5 ,?SECONDS); ?? ????? ???scheduler.schedule(new ?Runnable()?{ ?? ????public ?void ?run()?{ ?? ?????beeperHandle.cancel(true ); ?? ?????beeperHandle2.cancel(true ); ?? ?????scheduler.shutdown(); ?? ????} ?? ???},?30 ,?SECONDS); ?? } ?? }??
package test;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 {
/*** @param args*/
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));}};// 1秒鐘后運行,并每隔2秒運行一次final ScheduledFuture beeperHandle = scheduler.scheduleAtFixedRate(beeper, 1, 2, SECONDS);// 2秒鐘后運行,并每次在上次任務運行完后等待5秒后重新運行final ScheduledFuture beeperHandle2 = scheduler.scheduleWithFixedDelay(beeper, 2, 5, SECONDS);// 30秒后結束關閉任務,并且關閉Schedulerscheduler.schedule(new Runnable() {public void run() {beeperHandle.cancel(true);beeperHandle2.cancel(true);scheduler.shutdown();}}, 30, SECONDS);
}
}
可能的運行結果:
Java代碼 ?
Mon?Jun?06 ?21 :26 :52 ?CST?2011 ?beep?1 ?? Mon?Jun?06 ?21 :26 :53 ?CST?2011 ?beep?2 ?? Mon?Jun?06 ?21 :26 :54 ?CST?2011 ?beep?3 ?? Mon?Jun?06 ?21 :26 :56 ?CST?2011 ?beep?4 ?? Mon?Jun?06 ?21 :26 :58 ?CST?2011 ?beep?5 ?? Mon?Jun?06 ?21 :26 :58 ?CST?2011 ?beep?6 ?? Mon?Jun?06 ?21 :27 :00 ?CST?2011 ?beep?7 ?? Mon?Jun?06 ?21 :27 :02 ?CST?2011 ?beep?8 ?? Mon?Jun?06 ?21 :27 :03 ?CST?2011 ?beep?9 ?? Mon?Jun?06 ?21 :27 :04 ?CST?2011 ?beep?10 ?? Mon?Jun?06 ?21 :27 :06 ?CST?2011 ?beep?11 ?? Mon?Jun?06 ?21 :27 :08 ?CST?2011 ?beep?12 ?? Mon?Jun?06 ?21 :27 :08 ?CST?2011 ?beep?13 ?? Mon?Jun?06 ?21 :27 :10 ?CST?2011 ?beep?14 ?? Mon?Jun?06 ?21 :27 :12 ?CST?2011 ?beep?15 ?? Mon?Jun?06 ?21 :27 :13 ?CST?2011 ?beep?16 ?? Mon?Jun?06 ?21 :27 :14 ?CST?2011 ?beep?17 ?? Mon?Jun?06 ?21 :27 :16 ?CST?2011 ?beep?18 ?? Mon?Jun?06 ?21 :27 :18 ?CST?2011 ?beep?19 ?? Mon?Jun?06 ?21 :27 :18 ?CST?2011 ?beep?20 ?? Mon?Jun?06 ?21 :27 :20 ?CST?2011 ?beep?21 ??
Mon Jun 06 21:26:52 CST 2011 beep 1
Mon Jun 06 21:26:53 CST 2011 beep 2
Mon Jun 06 21:26:54 CST 2011 beep 3
Mon Jun 06 21:26:56 CST 2011 beep 4
Mon Jun 06 21:26:58 CST 2011 beep 5
Mon Jun 06 21:26:58 CST 2011 beep 6
Mon Jun 06 21:27:00 CST 2011 beep 7
Mon Jun 06 21:27:02 CST 2011 beep 8
Mon Jun 06 21:27:03 CST 2011 beep 9
Mon Jun 06 21:27:04 CST 2011 beep 10
Mon Jun 06 21:27:06 CST 2011 beep 11
Mon Jun 06 21:27:08 CST 2011 beep 12
Mon Jun 06 21:27:08 CST 2011 beep 13
Mon Jun 06 21:27:10 CST 2011 beep 14
Mon Jun 06 21:27:12 CST 2011 beep 15
Mon Jun 06 21:27:13 CST 2011 beep 16
Mon Jun 06 21:27:14 CST 2011 beep 17
Mon Jun 06 21:27:16 CST 2011 beep 18
Mon Jun 06 21:27:18 CST 2011 beep 19
Mon Jun 06 21:27:18 CST 2011 beep 20
Mon Jun 06 21:27:20 CST 2011 beep 21
許多長時間運行的應用有時候需要定時運行任務完成一些諸如統計、優化等工作,比如在電信行業中處理用戶話單時,需要每隔1分鐘處理話單;網站每天凌晨統計用戶訪問量、用戶數;大型超市凌晨3點統計當天銷售額、以及最熱賣的商品;每周日進行數據庫備份;公司每個月的10號計算工資并進行轉帳等,這些都是定時任務。通過 java 的并發庫concurrent可以輕松的完成這些任務,而且非常的簡單。 為了退出進程,上面的代碼中加入了關閉Scheduler的操作。而對于24小時運行的應用而言,是沒有必要關閉Scheduler的。
http://kanglecjr.iteye.com/blog/1071042
java.util.concurrent 之三: 出發--等待--匯合--再出發 Javathread旅游工作
在實際應用中,有時候需要多個線程同時工作以完成同一件事情,而且在完成過程中,往往會等待其他線程都完成某一階段后再執行,等所有線程都到達某一個階段后再統一執行。
??? 比如有幾個旅行團需要途經深圳、廣州、韶關、長沙最后到達武漢。旅行團中有自駕游的,有徒步的,有乘坐旅游大巴的;這些旅行團同時出發,并且每到一個目的地,都要等待其他旅行團到達此地后再同時出發,直到都到達終點站武漢。
? 這時候 CyclicBarrier 就可以派上用場。CyclicBarrier最重要的屬性就是參與者個數,另外最要方法是await()。當所有線程都調用了await()后,就表示這些線程都可以繼續執行,否則就會等待。
Java代碼 ?
package ?test; ???? 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{ ???????? ????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(); ?? ??} ?? }?? package test;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{// 徒步需要的時間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();}
}
可能的執行結果:
Java代碼 ?
21 :47 :18 :?SelfTour?Reached?Shenzhen ??21 :47 :19 :?BusTour?Reached?Shenzhen ??21 :47 :22 :?WalkTour?Reached?Shenzhen ??21 :47 :25 :?SelfTour?Reached?Guangzhou ??21 :47 :26 :?BusTour?Reached?Guangzhou ??21 :47 :30 :?WalkTour?Reached?Guangzhou ??21 :47 :34 :?SelfTour?Reached?Shaoguan ??21 :47 :36 :?BusTour?Reached?Shaoguan ??21 :47 :45 :?WalkTour?Reached?Shaoguan ??21 :47 :49 :?SelfTour?Reached?Changsha ??21 :47 :51 :?BusTour?Reached?Changsha ??21 :48 :00 :?WalkTour?Reached?Changsha ??21 :48 :05 :?SelfTour?Reached?Wuhan ??21 :48 :07 :?BusTour?Reached?Wuhan ??21 :48 :10 :?WalkTour?Reached?Wuhan??
http://kanglecjr.iteye.com/blog/1071069
java.util.concurrent 之四:LinkedBlockingQueue Javathread
并發庫中的BlockingQueue是一個比較好玩的類,顧名思義,就是阻塞隊列。該類主要提供了兩個方法put()和take(),前者將一個對象放到隊列尾部,如果隊列已經滿了,就等待直到有空閑節點;后者從head取一個對象,如果沒有對象,就等待直到有可取的對象。
Java代碼 ?
package ?test; ???? import ?java.util.concurrent.BlockingQueue; ??import ?java.util.concurrent.ExecutorService; ??import ?java.util.concurrent.Executors; ??import ?java.util.concurrent.LinkedBlockingQueue; ???? public ?class ?MyBlockingQueue?extends ?Thread{ ??????public ?static ?BlockingQueue<String>?queue=new ?LinkedBlockingQueue<String>(3 ); ?? ????private ?int ?index; ?? ????public ?MyBlockingQueue(int ?i){ ?? ????????this .index=i; ?? ????} ?? ?? ????public ?void ?run(){ ?? ????????try { ?? ????????????queue.put(String.valueOf(this .index)); ?? ????????????System.out.println("put?{" +this .index+"}?into?queue!" ); ?? ????????}catch (Exception?e){ ?? ????????????e.printStackTrace(); ?? ????????} ?? ????} ?? ???? ?? ????public ?static ?void ?main(String?args[]){ ?? ????????ExecutorService?service=Executors.newCachedThreadPool(); ?? ????????for (?int ?i=0 ;?i<10 ;?i++){ ?? ????????????service.submit(new ?MyBlockingQueue(i)); ?? ????????} ?? ????????Thread?thread?=?new ?Thread(){ ?? ????????????public ?void ?run(){ ?? ????????????????try { ?? ????????????????????while (true ){ ?? ????????????????????????Thread.sleep((int )(Math.random()*1000 )); ?? ????????????????????????if (MyBlockingQueue.queue.isEmpty())?break ; ?? ????????????????????????String?str=MyBlockingQueue.queue.take(); ?? ????????????????????????System.out.println("take?{" ?+?str+"}?out?of?queue!" ); ?? ????????????????????} ?? ????????????????}catch (Exception?e){ ?? ????????????????????e.printStackTrace(); ?? ????????????????} ?? ????????????} ?? ????????}; ?? ????????service.submit(thread); ?? ????????service.shutdown(); ?? ????} ?? ???? ?? }????????? package test;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;public class MyBlockingQueue extends Thread{public static BlockingQueue<String> queue=new LinkedBlockingQueue<String>(3);private int index;public MyBlockingQueue(int i){this.index=i;}public void run(){try{queue.put(String.valueOf(this.index));System.out.println("put {"+this.index+"} into queue!");}catch(Exception e){e.printStackTrace();}}public static void main(String args[]){ExecutorService service=Executors.newCachedThreadPool();for( int i=0; i<10; i++){service.submit(new MyBlockingQueue(i));}Thread thread = new Thread(){public void run(){try{while(true){Thread.sleep((int)(Math.random()*1000));if(MyBlockingQueue.queue.isEmpty()) break;String str=MyBlockingQueue.queue.take();System.out.println("take {" + str+"} out of queue!");}}catch(Exception e){e.printStackTrace();}}};service.submit(thread);service.shutdown();}}
可能的運行結果:
Java代碼 ?
put?{0 }?into?queue! ?? put?{1 }?into?queue! ?? put?{3 }?into?queue! ?? take?{0 }?out?of?queue! ?? put?{2 }?into?queue! ?? take?{1 }?out?of?queue! ?? put?{7 }?into?queue! ?? take?{3 }?out?of?queue! ?? put?{5 }?into?queue! ?? take?{2 }?out?of?queue! ?? put?{4 }?into?queue! ?? take?{7 }?out?of?queue! ?? put?{6 }?into?queue! ?? put?{9 }?into?queue! ?? take?{5 }?out?of?queue! ?? take?{4 }?out?of?queue! ?? put?{8 }?into?queue! ?? take?{6 }?out?of?queue! ?? take?{9 }?out?of?queue! ?? take?{8 }?out?of?queue!??
http://kanglecjr.iteye.com/blog/1071107
java.util.concurrent 之五:倒計數的鎖 Javathread
從名字可以看出,CountDownLatch是一個倒數計數的鎖,當倒數到0時觸發事件,也就是開鎖,其他人就可以進入了。在一些應用場合中,需要等待某個條件達到要求后才能做后面的事情;同時當線程都完成后也會觸發事件,以便進行后面的操作。
CountDownLatch最重要的方法是countDown()和await(),前者主要是倒數一次,后者是等待倒數到0,如果沒有到達0,就只有阻塞等待了。
一個CountDownLatch實例是不能重復使用的,也就是說它是一次性的,鎖一經被打開就不能再關閉使用了,如果想重復使用,請考慮使用CyclicBarrier。
下面的例子簡單的說明了CountDownLatch的使用方法,模擬了100米賽跑,10名選手已經準備就緒,只等裁判一聲令下。當所有人都到達終點時,比賽結束。
同樣,線程池需要顯式shutdown。
Java代碼 ?
package ?test; ???? 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<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(); ?? ????} ?? }?? package test;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);//10名選手final ExecutorService exec=Executors.newFixedThreadPool(10);for(int index=0; index<10;index++){final int NO=index + 1;//Cannot refer to a non-final variable NO inside an inner class defined in a different methodRunnable 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();}
}
可能的結果:
Java代碼 ?
Game?Start ?? No.4 ?arrived ?? No.6 ?arrived ?? No.8 ?arrived ?? No.5 ?arrived ?? No.10 ?arrived ?? No.3 ?arrived ?? No.2 ?arrived ?? No.7 ?arrived ?? No.1 ?arrived ?? No.9 ?arrived ?? Game?Over??
?
http://kanglecjr.iteye.com/blog/1071199 java.util.concurrent 之六:使用Future類和Callable類 Java瀏覽器thread 有時候在實際應用中,某些操作很耗時,但又不是不可或缺的步驟。比如用網頁瀏覽器瀏覽新聞時,最重要的是顯示文字內容,至于與新聞相匹配的圖片就沒有那么重要的,所以此時首先保證文字信息先顯示,而圖片信息會后顯示,但又不能不顯示,由于下載圖片是一個耗時的操作,所以必須一開始就得下載。 Java的并發庫的Future類 就可以滿足這個要求。Future的重要方法包括get()和cancel( ),get()獲取數據對象,如果數據沒有加載,就會阻塞直到取到數據,而 cancel()是取消數據加載。另外一個get(timeout)操作 ,表示如果在timeout時間內沒有取到就失敗返回,而不再阻塞。 下面的Demo簡單的說明了Future的使用方法:一個非常耗時的操作必須一開始啟動,但又不能一直等待;其他重要的事情又必須做,等完成后,就可以做不重要的事情。 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?=?(String)task.get(); ?? ????????System.out.println(obj); ?? ?????????? ????????exec.shutdown(); ?? ????} ?? }?? 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 = (String)task.get();System.out.println(obj);//關閉線程池exec.shutdown();}
}
運行結果:
Java代碼 ?
Let's?do ?important?things. ?? Other?less?important?but?longtime?things.?? Let's do important things.
Other less important but longtime things.
http://kanglecjr.iteye.com/blog/1071200
java.util.concurrent 之七:先下載完成的圖片先顯示 Java瀏覽器Webthread 考慮以下場景:瀏覽網頁時,瀏覽器用了5個線程下載網頁中的圖片文件,由于圖片大小、網站訪問速度等諸多因素的影響,完成圖片下載的時間就會有很大的不同。先下載完成的圖片就會被先顯示到界面上,反之,后下載的圖片就后顯示。
Java的并發庫的CompletionService可以滿足這種場景要求。該接口有兩個重要方法:submit()和take()。submit用于提交一個runnable或者callable,一般會提交給一個線程池處理;而take就是取出已經執行完畢runnable或者callable實例的Future對象,如果沒有滿足要求的,就等待了。
CompletionService還有一個對應的方法poll,該方法與take類似,只是不會等待,如果沒有滿足要求,就返回null對象 。
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?=?(String)task.get(); ?? ????????????System.out.println(img); ?? ????????}??? ?? ????????System.out.println("End" ); ?? ?????????? ????????exec.shutdown(); ?? ????} ?? }?? 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 = (String)task.get();System.out.println(img);} System.out.println("End");//關閉線程池exec.shutdown();}
}
運行結果:
Java代碼 ?
Show?web?content ?? Downloaded?Image?2 ?? Downloaded?Image?3 ?? Downloaded?Image?0 ?? Downloaded?Image?4 ?? Downloaded?Image?1 ?? End??
總結
以上是生活随笔 為你收集整理的java.util.concurrent 编程范例 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。