Java多線程-新特性-線程池

Sun在Java5中,對Java線程的類庫作了大量的擴展,其中線程池就是Java5的新特徵之一,除了線程池以外,還有不少多線程相關的內容,爲多線程的編程帶來了極大便利。爲了編寫高效穩定可靠的多線程程序,線程部分的新增內容顯得尤其重要。

有關Java5線程新特徵的內容所有在java.util.concurrent下面,裏面包含數目衆多的接口和類,熟悉這部分API特徵是一項艱難的學習過程。目前有關這方面的資料和書籍都少之又少,大部分介紹線程方面書籍還停留在java5以前的知識層面上。java

在Java5以前,要實現一個線程池是至關有難度的,如今Java5爲咱們作好了一切,咱們只須要按照提供的API來使用,便可享受線程池帶來的極大便利。編程

線程池的基本思想仍是一種對象池的思想,開闢一塊內存空間,裏面存放了衆多(未死亡)的線程,池中線程執行調度由池管理器來處理。當有線程任務時,從池中取一個,執行完成後線程對象歸池,這樣能夠避免反覆建立線程對象所帶來的性能開銷,節省了系統的資源。
緩存

Java5提供5種類型的線程池,分別以下:服務器

一:newCachedThreadPool-可變尺寸的線程池(緩存線程池) 
(1)緩存型池子,先查看池中有沒有之前創建的線程,若是有,就reuse(重用),若是沒有,就創建一個新的線程加入池中; 
(2)緩存型池子,一般用於執行一些生存週期很短的異步型任務;所以一些面向鏈接的daemon型server中用得很少; 
(3)能reuse(重用)的線程,必須是timeout IDLE內的池中線程,缺省timeout是60s,超過這個IDLE時長,線程實例將被終止及移出池; 
(4)注意,放入CachedThreadPool的線程沒必要擔憂其結束,超過TIMEOUT不活動,其會自動被終止。多線程

二:newFixedThreadPool-固定大小的線程池 
(1)newFixedThreadPool與cacheThreadPool差很少,也是能reuse就用,但不能隨時建新的線程; 
(2)其獨特之處:任意時間點,最多隻能有固定數目的活動線程存在,此時若是有新的線程要創建,只能放在另外的隊列中等待,直到當前的線程中某個線程終止直接被移出池子; 
(3)和cacheThreadPool不一樣,FixedThreadPool沒有IDLE機制(可能也有,但既然文檔沒提,確定很是長,相似依賴上層的TCP或UDP IDLE機制之類的),因此FixedThreadPool多數針對一些很穩定很固定的正規併發線程,多用於服務器; 
(4)從方法的源代碼看,cache池和fixed池調用的是同一個底層池,只不過參數不一樣:
fixed池線程數固定,而且是0秒IDLE(無IDLE);
cache池線程數支持0-Integer.MAX_VALUE(顯然徹底沒考慮主機的資源承受能力),60秒IDLE。併發

三:ScheduledThreadPool-調度線程池 
(1)調度型線程池; 
(2)這個池子裏的線程能夠按schedule依次delay執行,或週期執行。異步

四:SingleThreadExecutor-單例線程池 
(1)單例線程,任意時間池中只能有一個線程; 
(2)用的是和cache池和fixed池相同的底層池,但線程數目是1-1,0秒IDLE(無IDLE)。ide

package cn.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 線程池用法
 * 
 * @author 林計欽
 * @version 1.0 2013-7-25 上午10:00:46
 */
public class ThreadPoolTest {
    public static void main(String[] args) {
        ThreadPoolTest test=new ThreadPoolTest();
        
        //建立一個可重用固定線程數的線程池 
        ExecutorService pool = Executors.newFixedThreadPool(2); 
        //建立實現了Runnable接口對象,Thread對象固然也實現了Runnable接口 
        Thread t1 = test.new MyThread(); 
        Thread t2 = test.new MyThread(); 
        Thread t3 = test.new MyThread(); 
        Thread t4 = test.new MyThread(); 
        Thread t5 = test.new MyThread(); 
        //將線程放入池中進行執行 
        pool.execute(t1); 
        pool.execute(t2); 
        pool.execute(t3); 
        pool.execute(t4); 
        pool.execute(t5); 
        //關閉線程池 
        pool.shutdown(); 
    }
    
    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "正在執行。");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

5、自定義線程池
ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
參數:
corePoolSize 
核心線程數,核心線程會一直存活,即便沒有任務須要處理。當線程數小於核心線程數時,即便現有的線程空閒,線程池也會優先建立新線程來處理任務,而不是直接交給現有的線程處理。
核心線程在allowCoreThreadTimeout被設置爲true時會超時退出,默認狀況下不會退出。性能

maximumPoolSize
當線程數大於或等於核心線程,且任務隊列已滿時,線程池會建立新的線程,直到線程數量達到maxPoolSize。若是線程數已等於maxPoolSize,且任務隊列已滿,則已超出線程池的處理能力,線程池會拒絕處理任務而拋出異常。學習

keepAliveTime 
當線程空閒時間達到keepAliveTime,該線程會退出,直到線程數量等於corePoolSize。若是allowCoreThreadTimeout設置爲true,則全部線程均會退出直到線程數量爲0。

unit 
keepAliveTime 參數的時間單位。

workQueue 
執行前用於保持任務的隊列。此隊列僅保持由 execute 方法提交的 Runnable 任務。

拋出:
IllegalArgumentException - 若是corePoolSize或keepAliveTime小於零,或者maximumPoolSize小於或等於零,或者corePoolSize 大於maximumPoolSize。
NullPointerException - 若是workQueue爲null

eg、
//建立等待隊列 
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(20); 
//建立一個單線程執行程序,它可安排在給定延遲後運行命令或者按期地執行。 
ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 2, TimeUnit.MILLISECONDS, queue); 
//建立實現了Runnable接口對象,Thread對象固然也實現了Runnable接口 
Thread t1 = new MyThread(); 
Thread t2 = new MyThread(); 
//將線程放入池中進行執行 
pool.execute(t1); 
pool.execute(t2); 
//關閉線程池 
pool.shutdown();

package cn.thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 自定義鏈接池
 * 
 * @author 林計欽
 * @version 1.0 2013-7-25 上午10:09:17
 */
public class ThreadPoolExecutorTest {

    public static void main(String[] args) {
        ThreadPoolTest test = new ThreadPoolTest();

        // 建立等待隊列
        BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(20);
        // 建立一個單線程執行程序,它可安排在給定延遲後運行命令或者按期地執行。
        ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 2, TimeUnit.MILLISECONDS, bqueue);
        // 建立實現了Runnable接口對象,Thread對象固然也實現了Runnable接口
        Thread t1 = test.new MyThread();
        Thread t2 = test.new MyThread();
        Thread t3 = test.new MyThread();
        Thread t4 = test.new MyThread();
        Thread t5 = test.new MyThread();
        Thread t6 = test.new MyThread();
        Thread t7 = test.new MyThread();
        // 將線程放入池中進行執行
        pool.execute(t1);
        pool.execute(t2);
        pool.execute(t3);
        pool.execute(t4);
        pool.execute(t5);
        pool.execute(t6);
        pool.execute(t7);
        // 關閉線程池
        pool.shutdown();
    }

    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "正在執行。");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
相關文章
相關標籤/搜索