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());
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。