線程池

1 爲什麼要用線程池?
  a 單個任務處理的時間很短而請求的數目卻是巨大的。
 
  b 每當一個請求到達就創建一個新線程,然後在新線程中爲請求服務。
 
    創建一個新線程的開銷很大;服務器在創建和銷燬線程上花費的時間
    和消耗的系統資源要比花在處理實際的用戶請求的時間和資源更多。
    
  c 活動的線程也消耗系統資源。
 

2 線程池的優點
  在請求到達時線程已經存在,所以無意中也消除了線程創建所帶來的延遲。
  這樣,就可以立即爲請求服務,使應用程序響應更快。
  而且,通過適當地調整線程池中的線程數目,也就是當請求的數目超過某個閾值時,
  就強制其它任何新到的請求一直等待,直到獲得一個線程來處理爲止,從而可以防止資源不足。

3 使用線程池的風險

  死鎖  資源不足  併發錯誤 線程泄漏  請求過載
 
 
4 有效使用線程池的準則

調整池的大小  


無須編寫您自己的池:
用程序開放源碼庫 util.concurrent ,它包括互斥、信號量、
諸如在併發訪問下執行得很好的隊列和散列表之類集合類以及幾個工作隊列實現。
該包中的 PooledExecutor 類是一種有效的、廣泛使用的以工作隊列爲基礎的線程池的正確實現。
您無須嘗試編寫您自己的線程池,這樣做容易出錯,
相反您可以考慮使用 util.concurrent 中的一些實用程序。
參閱 參考資料以獲取鏈接和更多信息。

util.concurrent 庫也激發了 JSR 166,JSR 166
是一個 Java 社區過程(Java Community Process (JCP))工作組,
他們正在打算開發一組包含在 java.util.concurrent 包下的 Java 類庫中的併發實用程序,
這個包應該用於 Java 開發工具箱 1.5 發行版。

 
5 簡單線程池至少包含下列組成部分


    線程池管理器(ThreadPoolManager):用於創建並管理線程池
    工作線程(WorkThread): 線程池中線程
    任務接口(Task):每個任務必須實現的接口,以供工作線程調度任務的執行。
    任務隊列:用於存放沒有處理的任務。提供一種緩衝機制。
    
    簡而言之:
    1 建任務接口,然後去實現它。
    eq:
    接口:Business  方法:methods();
    
    TaskBusiness1   重寫:methods();
    TaskBusiness2   重寫:methods();
    TaskBusiness3   重寫:methods();
    
    2 然後將這些任務tasks放任務隊列taskQueue裏,工作線程爭奪任務隊列裏的任務。
    
    3 工作線程:run()方法裏 synchronized (taskQueue),不住的從隊列彈出任務處理。
    
    隊列taskQueue == null時,阻塞等待,線程沒有死,而是回到線程池。
    

    4 最後是銷燬線程池。


------------------------------

6 代碼如下:

接口或抽象類

public abstract class Business
{
    protected String info;
    
    abstract boolean methods();
    
    public String getInfo()
    {
        return info;
    }
}

--------------------------------

實現接口或抽象類1

public class TaskBusiness1 extends Business
{
    public TaskBusiness1(String info)
    {
        this.info = info;
    }
    
    public String getInfo()
    {
        return info;
    }
    
    @Override
    public boolean methods()
    {
        try
        {
            //任務的主體業務邏輯
            System.out.println("xxxxxxxxxxxxx");
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        return false;
    }
}

------------------------------

實現接口或抽象類2

public class TaskBusiness2 extends Business
{
    public TaskBusiness2(String info)
    {
        this.info = info;
    }
    
    public String getInfo()
    {
        return info;
    }
    
    @Override
    public boolean methods()
    {
        try
        {
            //任務的主體業務邏輯
            System.out.println("*************");
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        return false;
    }
}

-----------------------------------

線程池管理器

public class ThreadPoolManager
{
    private static ThreadPoolManager instance = null;
    
    
    private static Object mylock = ThreadPoolManager.class;
    /**
     * 任務隊列
     */
    private List<Business> taskQueue = Collections.synchronizedList(new LinkedList<Business>());
    
    /**
     * 工作線程(真正執行任務的線程)
     */
    private WorkThread[] workQueue;
    
    /**
     * 工作線程數量(默認工作線程數量是5)
     */
    private static int worker_num = 5;
    
    private ThreadPoolManager()
    {
        this(5);
    }
    
    private ThreadPoolManager(int num)
    {
        worker_num = num;
        workQueue = new WorkThread[worker_num];
        for (int i = 0; i < worker_num; i++)
        {
            workQueue[i] = new WorkThread();
        }
    }
    
    /**
     * 單例
     * <功能詳細描述>
     * @return
     * @see [類、類#方法、類#成員]
     */
    public static ThreadPoolManager getInstance()
    {
        synchronized(mylock)
        {
            if (instance == null)
            {
                instance = new ThreadPoolManager();
            }
            return instance;
        }
    }
    
    /**
     * 單個任務放入任務隊列
     * <功能詳細描述>
     * @param task
     * @see [類、類#方法、類#成員]
     */
    public void addTask(Business task)
    {
        //對任務隊列的操作要上鎖
        synchronized (taskQueue)
        {
            if (task != null)
            {
                taskQueue.add(task);
                taskQueue.notifyAll();
                System.out.println(task.getInfo() + " submit!");
            }
        }
    }
    
    /**
     * 批量任務放入任務隊列
     * <功能詳細描述>
     * @param tasks
     * @see [類、類#方法、類#成員]
     */
    public void BatchAddTask(Business[] tasks)
    {
        //對任務隊列的修改操作要上鎖
        synchronized (taskQueue)
        {
            for (Business e : tasks)
            {
                if (e != null)
                {
                    taskQueue.add(e);
                    taskQueue.notifyAll();
                    System.out.println(e.getInfo() + " submit!");
                }
            }
        }
    }
    
    /**
     * 銷燬線程池
     * <功能詳細描述>
     * @see [類、類#方法、類#成員]
     */
    public void destory()
    {
        System.out.println("pool begins to destory ...");
        for (int i = 0; i < worker_num; i++)
        {
            workQueue[i].stopThread();
            workQueue[i] = null;
        }
        //對任務隊列的操作要上鎖
        synchronized (taskQueue)
        {
            taskQueue.clear();
        }
        
        System.out.println("pool ends to destory ...");
    }
    
    /**
     *
     * 工作線程
     * <功能詳細描述>
     * @version  [版本號, 2014-1-3]
     * @see  [相關類/方法]
     * @since  [產品/模塊版本]
     */
    private class WorkThread extends Thread
    {
        /**
         * 運行狀態
         */
        private boolean isRuning = true;
        
        /**
         * 阻塞狀態
         */
        private boolean isWaiting = false;
        
        public WorkThread()
        {
            this.start();
        }
        
        /**
        * 如果任務進行中時,不能立刻終止線程,需要等待
        * 任務完成之後檢測到isRuning爲false的時候,退出run()方法
        * <功能詳細描述>
        * @see [類、類#方法、類#成員]
        */
        public void stopThread()
        {
            isRuning = false;
        }
        
        @Override
        public void run()
        {
            while (isRuning)
            {
                Business temp = null;
                //對任務隊列的操作要上鎖
                synchronized (taskQueue)
                {
                    //任務隊列爲空,等待新的任務加入
                    while (isRuning && taskQueue.isEmpty())
                    {
                        try
                        {
                            taskQueue.wait(20);
                        }
                        catch (InterruptedException e)
                        {
                            System.out.println("InterruptedException occre...");
                            e.printStackTrace();
                        }
                    }
                    if (isRuning)
                    {
                        temp = taskQueue.remove(0);
                    }
                }
                //當等待新任務加入時候,終止線程(調用stopThread函數)造成 temp = null
                if (temp != null)
                {
                    //任務的業務方法
                    isWaiting = false;
                    temp.methods();
                    isWaiting = true;
                    System.out.println(temp.getInfo() + " is finished");
                }
            }
        }
    }
}

---------------------------------------------

test:

public class ThreadPoolManagerTest
{
    /**
     * 任務類別1
     */
    public static final String FLAG_BUSINESS1 = "1";
    
    /**
     * 任務類別2
     */
    public static final String FLAG_BUSINESS2 = "2";
    
    public static void main(String[] args)
    {
        //7 個任務
        Business[] tasks1 = createBatchTask(3, FLAG_BUSINESS1);
        Business[] tasks2 = createBatchTask(5, FLAG_BUSINESS2);
        //5 個工作線程
        ThreadPoolManager pool = ThreadPoolManager.getInstance();
        pool.BatchAddTask(tasks1);
        pool.BatchAddTask(tasks2);
        //pool.destory();
    }
    
    /**
     * 批量創建工作任務
     * <功能詳細描述>
     * @param n  個數
     * @param flag 任務類別
     * @return
     * @see [類、類#方法、類#成員]
     */
    private static Business[] createBatchTask(int n, String flag)
    {
        Business[] tasks = null;
        if (StringUtils.equals(FLAG_BUSINESS1, flag))
        {
            tasks = new TaskBusiness1[n];
            for (int i = 0; i < n; i++)
            {
                tasks[i] = new TaskBusiness1("task1 id is " + i);
            }
        }
        else
        {
            tasks = new TaskBusiness2[n];
            for (int i = 0; i < n; i++)
            {
                tasks[i] = new TaskBusiness2("task2 id is " + i);
            }
        }
        return tasks;
    }
}


-------------------

結果:

task1 id is 0 submit!
task1 id is 1 submit!
task1 id is 2 submit!
xxxxxxxxxxxxx
xxxxxxxxxxxxx
xxxxxxxxxxxxx
task2 id is 0 submit!
task2 id is 1 submit!
task2 id is 2 submit!
task2 id is 3 submit!
task2 id is 4 submit!
*************
*************
task1 id is 1 is finished
*************
task2 id is 0 is finished
*************
task1 id is 2 is finished
*************
task1 id is 0 is finished
task2 id is 1 is finished
task2 id is 3 is finished
task2 id is 4 is finished
task2 id is 2 is finished




發佈了8 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章