歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java多線程之ThreadPool

這裡演示了普通線程池以及帶有返回值的線程池的使用方式

  1. package com.jadyer.thread.pool; 
  2.  
  3. import java.util.Random; 
  4. import java.util.concurrent.Callable; 
  5. import java.util.concurrent.CompletionService; 
  6. import java.util.concurrent.ExecutionException; 
  7. import java.util.concurrent.ExecutorCompletionService; 
  8. import java.util.concurrent.ExecutorService; 
  9. import java.util.concurrent.Executors; 
  10. import java.util.concurrent.Future; 
  11. import java.util.concurrent.TimeUnit; 
  12.  
  13. /** 
  14.  * ThreadPool Test 
  15.  * @see ================================================================================================ 
  16.  * @see 線程與進程的區別 
  17.  * @see 1)多個進程的內部數據和狀態是完全獨立的,而多線程則會共享一塊內存空間和一組系統資源,有可能互相影響 
  18.  * @see 2)線程本身的數據通常只有寄存器數據,以及一個程序執行時使用的堆棧。所以線程的切換比進程切換的負擔要小 
  19.  * @see ================================================================================================ 
  20.  * @see 線程的啟動方式和消亡 
  21.  * @see 1)以Thread.start()啟動時,JVM會以線程的方式運行它。start()首先會為線程的執行准備系統資源,然後才去調用run方法 
  22.  * @see 2)以Thread.run()啟動時,JVM會以普通方法運行它。此時就不會存在線程所特有的交替執行的效果 
  23.  * @see 3)一個線程類的兩個對象,同時以start()方式運行時,JVM仍會把它們當作兩個線程類來執行 
  24.  * @see 4)終止線程時,絕對不能使用stop()方法,而應該讓run()自然結束 
  25.  * @see ================================================================================================ 
  26.  * @author 宏宇 
  27.  * @create Feb 29, 2012 1:13:43 AM 
  28.  */ 
  29. public class ThreadPoolTest { 
  30.     public static void main(String[] args) { 
  31.         new ThreadPoolTest().threadPoolTest(); 
  32.         new ThreadPoolTest().threadPoolScheduledTest(); 
  33.         new ThreadPoolTest().threadPoolCallbaleAndFutureSignTest(); 
  34.         new ThreadPoolTest().threadPoolCallbaleAndFutureMoreTest(); 
  35.     } 
  36.      
  37.     /** 
  38.      * 創建線程池的幾種方式 
  39.      * @see Executors.newFixedThreadPool(3);     //創建固定大小的線程池 
  40.      * @see Executors.newCachedThreadPool();     //創建緩存線程池。它會根據實際請求的線程數量動態創建線程 
  41.      * @see Executors.newSingleThreadExecutor(); //創建單個線程池。它可以實現線程死掉後重新啟動的效果,但實際啟動的是"替補線程" 
  42.      */ 
  43.     public void threadPoolTest(){ 
  44.         //newSingleThreadExecutor()的好處就是,若池中的線程死了,它會把一個"替補的線程"扶上位,即它會保證池中始終有一個線程存在  
  45.         ExecutorService threadPool = Executors.newSingleThreadExecutor(); 
  46.         for(int i=1; i<=10; i++) { 
  47.             final int task = i; 
  48.             threadPool.execute(new MyThread(task)); //注意execute()的返回值是void  
  49.         } 
  50.         System.out.println("all of 10 tasks have committed......"); 
  51.          
  52.         //線程池中的任務均執行完畢後,關閉線程池  
  53.         threadPool.shutdown(); 
  54.     } 
  55.      
  56.     /** 
  57.      * 線程池啟動定時器 
  58.      * @see Executors.newScheduledThreadPool(3).schedule();            //創建並執行在給定延遲後啟用的一次性操作 
  59.      * @see Executors.newScheduledThreadPool(3).scheduleAtFixedRate(); //首次啟動後,以固定的頻率自動執行操作 
  60.      * @see scheduleAtFixedRate()支持間隔重復任務的定時方式,但不直接支持絕對定時方式,我們需要轉換為相對時間的方式,來執行 
  61.      */ 
  62.     public void threadPoolScheduledTest(){ 
  63.         //10秒後自動執行一次  
  64.         //Executors.newScheduledThreadPool(3).schedule(new MyScheduledThread(), 10, TimeUnit.SECONDS);  
  65.         //6秒後首次執行,之後每2秒均自動執行一次  
  66.         Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new MyScheduledThread(), 6, 2, TimeUnit.SECONDS); 
  67.     } 
  68.      
  69.     /** 
  70.      * 線程池返回一個任務的值 
  71.      * @see 注意:這裡需使用java.util.concurrent.ExecutorService.submit()來提交,它會返回Future對象 
  72.      * @see 注意:Future取得的結果類型,與Callable返回的結果類型,必須一致。我們這裡是通過泛型來實現的 
  73.      */ 
  74.     public void threadPoolCallbaleAndFutureSignTest(){ 
  75.         ExecutorService threadPool =  Executors.newSingleThreadExecutor(); 
  76.         Future<String> future = threadPool.submit( 
  77.             new Callable<String>() { 
  78.                 @Override 
  79.                 public String call() throws Exception { 
  80.                     Thread.sleep(2000); 
  81.                     return "張起靈"; 
  82.                 }; 
  83.             } 
  84.         ); 
  85.         System.out.println("等待結果"); 
  86.         try { 
  87.             System.out.println("拿到結果:" + future.get()); //future.get(4, TimeUnit.SECONDS)  
  88.         } catch (InterruptedException e) { 
  89.             e.printStackTrace(); 
  90.         } catch (ExecutionException e) { 
  91.             e.printStackTrace(); 
  92.         } 
  93.     } 
  94.      
  95.     /** 
  96.      * 線程池返回多個任務的值 
  97.      * @see java.util.concurrent.CompletionService用於提交一組Callable任務 
  98.      * @see CompletionService.take()會返回已完成的一個Callable任務所對應的Future對象 
  99.      * @see 這就好比同時種植了幾塊菜地,然後等待收菜。收菜時,哪塊菜熟了,就先去收哪塊菜地的菜 
  100.      */ 
  101.     public void threadPoolCallbaleAndFutureMoreTest(){ 
  102.         ExecutorService threadPool =  Executors.newFixedThreadPool(5); 
  103.         CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool); 
  104.         for(int i=1; i<=5; i++){ 
  105.             final int taskCode = i; 
  106.             completionService.submit( 
  107.                 new Callable<Integer>(){ 
  108.                     @Override 
  109.                     public Integer call() throws Exception { 
  110.                         Thread.sleep(new Random().nextInt(5000)); 
  111.                         return taskCode; 
  112.                     } 
  113.                 } 
  114.             ); 
  115.         } 
  116.         for(int i=0; i<5; i++){ 
  117.             try { 
  118.                 System.out.println(completionService.take().get()); 
  119.             } catch (InterruptedException e) { 
  120.                 e.printStackTrace(); 
  121.             } catch (ExecutionException e) { 
  122.                 e.printStackTrace(); 
  123.             } 
  124.         } 
  125.     } 
  126.  
  127.  
  128. class MyThread implements Runnable{ 
  129.     private Integer task; 
  130.     public MyThread(Integer task){ 
  131.         this.task = task; 
  132.     } 
  133.     @Override 
  134.     public void run() { 
  135.         //這裡不需要寫成j,因為它和threadPoolTest()裡面的for()循環中的i並不是同一個方法中的變量,故其不會沖突  
  136.         for(int i=1; i<=10; i++) { 
  137.             try { 
  138.                 Thread.sleep(20); 
  139.             } catch (InterruptedException e) { 
  140.                 e.printStackTrace(); 
  141.             } 
  142.             System.out.println(Thread.currentThread().getName() + " is looping of " + i + " for  task of " + task); 
  143.         } 
  144.     } 
  145.  
  146.  
  147. class MyScheduledThread implements Runnable{ 
  148.     @Override 
  149.     public void run() { 
  150.         System.out.println("bombing......"); 
  151.     } 
Copyright © Linux教程網 All Rights Reserved