1. 程式人生 > >016.多執行緒-執行緒池的四種建立方式

016.多執行緒-執行緒池的四種建立方式

前言

為什麼要用執行緒池

經常建立、銷燬 執行緒,將是對系統資源的極大浪費。
因此,實際開發中我們將使用執行緒池來管理、複用 執行緒。
使用執行緒池,可以
1.降低資源消耗: 重複利用執行緒,減少建立和銷燬造成的消耗。
2.提升響應速度: 任務到達,不需要建立,立即執行。
3.提高可管理型: 執行緒是CPU排程和分派的基本單位,
如果無限制地建立,不僅會消耗系統資源,還會降低系統穩定性。
使用執行緒池可以統一進行 分配、調優和監控。

執行緒池的分類

ThreadPoolExecutor

ThreadPoolExecutor是執行緒池的真正實現,
他通過構造方法的一系列引數,來構成不同配置的執行緒池。
常用的構造方法有下面四個

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
RejectedExecutionHandler handler);
  • corePoolSize: 核心池的大小。 當有任務來之後,就會建立一個執行緒去執行任務,當執行緒池中的執行緒數目達到corePoolSize後,就會把到達的任務放到快取隊列當中
  • maximumPoolSize: 執行緒池最大執行緒數,它表示線上程池中最多能建立多少個執行緒;
  • keepAliveTime: 表示執行緒沒有任務執行時最多保持多久時間會終止。
  • unit: 引數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性。
  • workQueue:一個阻塞佇列,提交的任務將會被放到這個佇列裡。
  • threadFactory:執行緒工廠,用來建立執行緒,主要是為了給執行緒起名字,預設工廠的執行緒名字:pool-1-thread-3。
  • handler:拒絕策略,當執行緒池裡執行緒被耗盡,且佇列也滿了的時候會呼叫。

執行緒池的四種建立方式

Java通過Executors(jdk1.5併發包)提供四種執行緒池,分別為:

  • newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。
    案例演示:

  • newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。

  • newScheduledThreadPool 建立一個定長執行緒池,支援定時及週期性任務執行。

  • newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。


newCachedThreadPool

建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,
若無可回收,則新建執行緒。

package cn.qbz.thread;

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

public class Test111907 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int temp = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "   i=" + temp);
                }
            });
        }
    }
}

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

newFixedThreadPool

建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。

package cn.qbz.thread;

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

public class Test111907 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int temp = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "   i=" + temp);
                }
            });
        }
    }
}

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }


newScheduledThreadPool

建立一個定長執行緒池,支援定時及週期性任務執行。

package cn.qbz.thread;

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

public class Test111907 {
    public static void main(String[] args) {
        final long begin = System.currentTimeMillis();
        ExecutorService executorService = Executors.newScheduledThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int temp = i;
            final long time = begin;
            executorService.schedule(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "   i=" + temp + "   time=" + (System.currentTimeMillis() - time));
                }
            }, 5, TimeUnit.SECONDS);
        }
    }
}

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
              new DelayedWorkQueue());
    }


newSingleThreadExecutor

建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,
保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。

package cn.qbz.thread;

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

public class Test111907 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int temp = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "   i=" + temp);
                }
            });
        }
    }
}