java中線程池的使用方法


1 引入線程池的原因

  由於線程的生命周期中包括創建、就緒、運行、阻塞、銷毀階段,當我們待處理的任務數目較小時,我們可以自己創建幾個線程來處理相應的任務,但當有大量的任務時,由於創建、銷毀線程需要很大的開銷,運用線程池這些問題就大大的緩解了。

2 線程池的使用

  我們只需要運用Executors類給我們提供的靜態方法,就可以創建相應的線程池:

  public static ExecutorSevice newSingleThreadExecutor()

  public static ExecutorSevice newFixedThreadPool()

  public static ExecutorSevice  newCachedThreadPool()

  newSingleThreadExecutor返回以個包含單線程的Executor,將多個任務交給此Exector時,這個線程處理完一個任務后接着處理下一個任務,若該線程出現異常,將會有一個新的線程來替代。

  newFixedThreadPool返回一個包含指定數目線程的線程池,如果任務數量多於線程數目,那么沒有沒有執行的任務必須等待,直到有任務完成為止。

  newCachedThreadPool根據用戶的任務數創建相應的線程來處理,該線程池不會對線程數目加以限制,完全依賴於JVM能創建線程的數量,可能引起內存不足。

  我們只需要將待執行的任務放入run方法中即可,將Runnable接口的實現類交給線程池的execute方法,作為它的一個參數,如下所示:

Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable(){
    public void run(){
       //執行的任務    
  }
}

  如果需要給任務傳遞參數,可以通過創建一個Runnable接口的實現類來完成。 

3 線程池使用的示例

  下面我們通過一個實例來說明線程池的使用方法,該實例模仿子HADOOP中作業初始化過程,也即利用線程池從隊列中取出作業並對作業進行初始化,其代碼如下:

package com.yueliming.ThreadPool;

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

public class FixedThreadPool {

    public static List<Double> queue;
    public ExecutorService threadPool;

    public FixedThreadPool() {
        queue = new ArrayList<Double>();
        //產生一個 ExecutorService 對象,這個對象帶有一個大小為 poolSize 的線程池,若任務數量大於 poolSize ,任務會被放在一個 queue 里順序執行。 
        threadPool = Executors.newFixedThreadPool(5);
    }

    public static void main(String[] args) {
        FixedThreadPool outer = new FixedThreadPool();
        FixedThreadPool.Manager inner = outer.new Manager();
        Thread consumer = new Thread(inner);

        Thread producer = new Thread() {//用於向queue中放入數據
            public void run() {
                while (true) {
                    synchronized (queue) {
                        double time = 1d;
                        long startTime = System.currentTimeMillis();
                        if (System.currentTimeMillis() - startTime >= time) {
                            startTime = System.currentTimeMillis();
                            for (int i = 0; i < 10; i++) {
                                queue.add((Math.random() * 10000));
                            }
                            queue.notify();
                        }
                    }
                }
            }
        };
        consumer.start();//啟動守護線程,采用線程池來從queue中讀取數據
        producer.start();
    }

    class Manager implements Runnable {
        int num = 0;
        public void run() {
            while (true) {
                try {
                    synchronized (queue) {
                        System.out.println("隊列的長度為:" + queue.size());
                        while (queue.isEmpty()) {
                            queue.wait();
                        }
                        double result = queue.remove(0);
                        num++;
                        System.out.println("成功從隊列中取到數據!" + num);
                        threadPool.execute(new ExecutorThread(result));
                    }
                } catch (InterruptedException t) {
                    break;
                }
            }
            threadPool.shutdown();
        }
    }

    class ExecutorThread implements Runnable {

        private double value;

        public ExecutorThread(double value) {
            this.value = value;
        }

        public void run() {
            System.out.println("This is " + Thread.currentThread().getName() + " " + value);
        }
    }
}
View Code

  其中內部類Manager為一個線程負責從隊列中獲取作業,並交給線程池去處理任務,有一個線程專門將數據放入到隊列中,也即每隔1ms向隊列中放入10個數據。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM