1、线程池的优势

(1)降低资源消耗,通过重复利用已创建的线程池减少线程创建和销毁带来的消耗
(2)提高效应速度,当任务来临时,不用等待线程的创建就能立即执行
(3)提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,线程池可以进行管理,统一分配和监控
总的来说线程池的主要特点就是:线程复用、控制最大并发数、管理线程

2、创建线程的三个c常用方法

(1)创建有固定线程数的方法,corePoolSize等于maximumPoolSize
ExecutorService threadPool = Executors.newFixedThreadPool(5);
(2)创建只有一个线程的线程池,corePoolSize等maximumPoolSize并且都等于1
ExecutorService threadPool2 = Executors.newSingleThreadExecutor();
(3)创建一个可缓存线程池,corePoolSize等于0,maximumPoolSize等于Integer.MAX_VALUE
ExecutorService threadPool3 = Executors.newCachedThreadPool();

3、底层创建线程的方法详解
Java底层创建线程池的源码

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

corePoolSize:线程池中的常驻核心线程数

maximumPoolSize:线程池中能够容纳的最大线程数

keepAliveTime:空余线程的存好时间,当线程池的数量超过

corePoolSize时,空闲时间达到keepAliveTime时,多余线程就会配销毁直到只剩余到corePoolSize的数量

TimeUnit:keepAliveTime的时间单位

workQueue:任务队列,当corePoolSize线程没有空闲的时候,不会马上扩充线程池的线程数,而是先将任务存放到workQueue中

threadFactory:常见线程池中的线程的线程工厂

handler:拒绝策略,当队列满了,且工作线程大于等于maximumPoolSize时,如何来拒绝请求执行的策略,Java中拒绝策略有四种,分别为AbortPolicy,默认拒绝策略,直接抛出
RejectedExecutionException 异常阻止系统正常运行;
DiscardPolicy,默默的丢弃无法处理的任务;DiscardOldestPolicy,丢弃队列中等待最久的任务;CallerRunsPolicy,调用者运行“一种调节机制,该策略就不会抛弃任务,也不会抛出异常,而是将某些任务回退给调用者

4、推荐使用的创建线程池的方式
上面的三种创建的三种线程池的方式,都推荐,推荐自定义线程池,原因请看源码,源码如下

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

前两种队列使用了LinkedBlockingQueue,而LinkedBlockingQueue从默认构造函数是

public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

它可以存储Integer.MAX_VALUE个任务,如果系统一直提交任务,而系统又处理缓慢容易引发OOM异常
后一个更不用说可以最大线程数可以创建到Integer.MAX_VALUE个线程更容易引发OOM异常,所以才要自定义线程池
5、自定义一个线程池

ExecutorService threadPool4 = new ThreadPoolExecutor(
                5,
                Runtime.getRuntime().availableProcessors()+1,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(9),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());

平安
1 声望0 粉丝