一、线程池的优点缓存
(1)下降资源消耗,经过重复利用已建立的线程池减小线程建立和销毁带来的消耗 (2)提升效应速度,当任务来临时,不用等待线程的建立就能当即执行 (3)提升线程的可管理性,线程是稀缺资源,若是无限制的建立,不只会消耗系统资源,还会下降系统的稳定性,线程池能够进行管理,统一分配和监控 总的来讲线程池的主要特色就是:线程复用、控制最大并发数、管理线程
二、建立线程的三个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();
三、底层建立线程的方法详解
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:线程池中的常驻核心线程数this
maximumPoolSize:线程池中可以容纳的最大线程数线程
keepAliveTime:空余线程的存好时间,当线程池的数量超过code
corePoolSize时,空闲时间达到keepAliveTime时,多余线程就会配销毁直到只剩余到corePoolSize的数量队列
TimeUnit:keepAliveTime的时间单位资源
workQueue:任务队列,当corePoolSize线程没有空闲的时候,不会立刻扩充线程池的线程数,而是先将任务存放到workQueue中get
threadFactory:常见线程池中的线程的线程工厂源码
handler:拒绝策略,当队列满了,且工做线程大于等于maximumPoolSize时,如何来拒绝请求执行的策略,Java中拒绝策略有四种,分别为AbortPolicy,默认拒绝策略,直接抛出
RejectedExecutionException 异常阻止系统正常运行;
DiscardPolicy,默默的丢弃没法处理的任务;DiscardOldestPolicy,丢弃队列中等待最久的任务;CallerRunsPolicy,调用者运行“一种调节机制,该策略就不会抛弃任务,也不会抛出异常,而是将某些任务回退给调用者
四、推荐使用的建立线程池的方式
上面的三种建立的三种线程池的方式,都推荐,推荐自定义线程池,缘由请看源码,源码以下
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异常,因此才要自定义线程池
五、自定义一个线程池
ExecutorService threadPool4 = new ThreadPoolExecutor( 5, Runtime.getRuntime().availableProcessors()+1, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(9), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());