1. 程式人生 > >執行緒池的建立和使用,不建議直接使用Executor建立

執行緒池的建立和使用,不建議直接使用Executor建立

實現執行緒池,有四種策略:

生成執行緒池採用了工具類Executors的靜態方法,以下是四種常見的執行緒池。

SingleThreadExecutor:單個後臺執行緒 (其緩衝佇列是無界的)。

建立一個單執行緒的執行緒池。這個執行緒池只有一個核心執行緒在工作,也就是相當於單執行緒序列執行所有任務。如果這個唯一的執行緒因為異常結束,那麼會有一個新的執行緒來替代它。此執行緒池保證所有任務的執行順序按照任務的提交順序執行。

 public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            ( new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit. MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

FixedThreadPool:只有核心執行緒的執行緒池,大小固定 (其緩衝佇列是無界的) 。

建立固定大小的執行緒池。每次提交一個任務就建立一個執行緒,直到執行緒達到執行緒池的最大大小。執行緒池的大小一旦達到最大值就會保持不變,如果某個執行緒因為執行異常而結束,那麼執行緒池會補充一個新執行緒。

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

CachedThreadPool:無界執行緒池,可以進行自動執行緒回收。

如果執行緒池的大小超過了處理任務所需要的執行緒,那麼就會回收部分空閒(60秒不執行任務)的執行緒,當任務數增加時,此執行緒池又可以智慧的新增新執行緒來處理任務。此執行緒池不會對執行緒池大小做限制,執行緒池大小完全依賴於作業系統(或者說JVM)能夠建立的最大執行緒大小。SynchronousQueue是一個是緩衝區為1的阻塞佇列。 

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

ScheduledThreadPool:核心執行緒池固定,大小無限的執行緒池。此執行緒池支援定時以及週期性執行任務的需求。

建立一個週期性執行任務的執行緒池。如果閒置,非核心執行緒池會在DEFAULT_KEEPALIVEMILLIS時間內回收。

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

提交任務方式

ExecutorService.execute(Runnable runable);

FutureTask task = ExecutorService.submit(Runnable runnable);

FutureTask<T> task = ExecutorService.submit(Runnable runnable,T Result);

FutureTask<T> task = ExecutorService.submit(Callable<T> callable);

package com.xyz.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

public class ExecutorsDemo {
	
	private final static Logger logger=LoggerFactory.getLogger(ExecutorsDemo.class);
	
	private static ThreadFactory nameThreadFactory=new ThreadFactoryBuilder()
			.setNameFormat("demo-pool-%d").build();

	/**
	 * corePoolSize - 池中所儲存的執行緒數,包括空閒執行緒。
	 * maximumPoolSize-池中允許的最大執行緒數。
	 * keepAliveTime - 當執行緒數大於核心時,此為終止前多餘的空閒執行緒等待新任務的最長時間。
	 * unit - keepAliveTime 引數的時間單位。
	 * workQueue - 執行前用於保持任務的佇列。此佇列僅保持由 execute方法提交的 Runnable任務。
	 * threadFactory - 執行程式建立新執行緒時使用的工廠。
	 * handler - 由於超出執行緒範圍和佇列容量而使執行被阻塞時所使用的處理程式。
	 */
	private static ExecutorService pool=new ThreadPoolExecutor(5, 10, 0L, 
			TimeUnit.MILLISECONDS, 
			new LinkedBlockingQueue<Runnable>(1024), nameThreadFactory,
new ThreadPoolExecutor.AbortPolicy());
	public static void main(String[] args) {
		
		for(int i=0;i<Integer.MAX_VALUE;i++) {
			pool.execute(new Thread() {

				@Override
				public void run() {
					logger.info(Thread.currentThread().getName());
				}
				
			});
		}
	}
}

Executors 返回執行緒池物件的弊端如下:
FixedThreadPool 和 SingleThreadExecutor : 允許請求的佇列長度為 Integer.MAX_VALUE,可能堆積大量的請求,從而導致OOM。
CachedThreadPool 和 ScheduledThreadPool : 允許建立的執行緒數量為 Integer.MAX_VALUE ,可能會建立大量執行緒,從而導致OOM。