BlockingQueue<Runnable> workQueue = null;
workQueue = new ArrayBlockingQueue<>(5);//基于数组的先进先出队列,有界
workQueue = new LinkedBlockingQueue<>();//基于链表的先进先出队列,无界
workQueue = new SynchronousQueue<>();//无缓冲的等待队列,无界html
RejectedExecutionHandler rejected = null;
rejected = new ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
rejected = new ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最先进入队列的任务删,以后再尝试加入队列
rejected = new ThreadPoolExecutor.CallerRunsPolicy();//若是添加到线程池失败,那么主线程会本身去执行该任务java
ExecutorService threadPool = null;
threadPool = Executors.newCachedThreadPool();//有缓冲的线程池,线程数 JVM 控制
threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池
threadPool = Executors.newScheduledThreadPool(2);
threadPool = Executors.newSingleThreadExecutor();//单线程的线程池,只有一个线程在工做
threadPool = new ThreadPoolExecutor();//默认线程池,可控制参数比较多数组
很简单,简单看名字就知道是装有线程的池子,咱们能够把要执行的多线程交给线程池来处理,和链接池的概念同样,经过维护必定数量的线程池来达到多个线程的复用。
安全
咱们知道不用线程池的话,每一个线程都要经过new Thread(xxRunnable).start()的方式来建立并运行一个线程,线程少的话这不会是问题,而真实环境可能会开启多个线程让系统和程序达到最佳效率,当线程数达到必定数量就会耗尽系统的CPU和内存资源,也会形成GC频繁收集和停顿,由于每次建立和销毁一个线程都是要消耗系统资源的,若是为每一个任务都建立线程这无疑是一个很大的性能瓶颈
。因此,线程池中的线程复用极大节省了系统资源,当线程一段时间再也不有任务处理时它也会自动销毁,而不会长驻内存。多线程
在java.util.concurrent包中咱们能找到线程池的定义,其中ThreadPoolExecutor
是咱们线程池核心类,首先看看线程池类的主要参数有哪些。并发
/** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters and default thread factory. */ 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; }
Executors
是jdk里面提供的建立线程池的工厂类,它默认提供了4种经常使用的线程池应用,而没必要咱们去重复构造。async
newFixedThreadPool
/** * Creates a thread pool that reuses a fixed number of threads * operating off a shared unbounded queue, using the provided * ThreadFactory to create new threads when needed. */ public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); }
newCachedThreadPool
/** * Creates a thread pool that creates new threads as needed, but * will reuse previously constructed threads when they are * available. These pools will typically improve the performance * of programs that execute many short-lived asynchronous tasks. */ public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
newSingleThreadExecutor
/** * Creates an Executor that uses a single worker thread operating * off an unbounded queue. (Note however that if this single * thread terminates due to a failure during execution prior to * shutdown, a new one will take its place if needed to execute * subsequent tasks.) Tasks are guaranteed to execute * sequentially, and no more than one task will be active at any * given time. Unlike the otherwise equivalent */ public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
newScheduledThreadPool
/** * Creates a thread pool that can schedule commands to run after a * given delay, or to execute periodically. */ public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
缓冲队列BlockingQueue简介:ide
BlockingQueue是双缓冲队列。BlockingQueue内部使用两条队列,容许两个线程同时向队列一个存储,一个取出操做。在保证并发安全的同时,提升了队列的存取效率。
能够先随便定义一个固定大小的线程池函数
ExecutorService es = Executors.newFixedThreadPool(3);
提交一个线程性能
es.submit(xxRunnble); es.execute(xxRunnble);
submit和execute分别有什么区别呢?
咱们来看看execute()到底方法是如何处理的:
es.shutdown();
再也不接受新的任务,以前提交的任务等执行结束再关闭线程池。
es.shutdownNow();
再也不接受新的任务,试图中止池中的任务再关闭线程池,返回全部未处理的线程list列表。
线程池主要用来解决线程生命周期开销问题和资源不足问题。经过对多个任务重复使用线程,线程建立的开销就被分摊到多个任务上,并且因为在请求到达时线程已经存在,因此消除线程建立所带来的延迟。这样,就能够当即为请求服务,使应用程序响应更快。另外,经过适当的调整线程中的线程数目能够防止出现资源不足。