- 线程池的优点?
- 线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用。
- 线程池为线程生命周期开销问题和资源不足问题提供了解决方案。可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。
-
线程池的创建
-
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
- corePoolSize:线程池核心线程数量
- maximumPoolSize:线程池最大线程数量
- keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间,所以如果任务很多,并且每个任务执行的时间比较短,可以适当调大这个参数来提高线程的利用率。
- unit:存活时间的单位,可选的单位:天(DAYS),小时(HOURS),分钟(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS)和纳秒(NANOSECONDS)
- workQueue:存放任务的队列。用来存放我们所定义的任务处理线程,BlockingQueue是一种带锁的阻塞队列。BlockingQueue有四种选择:(1)ArrayBlockingQueue,是一种基于数组的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行操作;2)LinkedBlockingQueue,是一个基于链表的阻塞队列,此队列也按FIFO (先进先出)对元素进行操作,吞吐量通常要高于ArrayBlockingQueue, Executors.newFixedThreadPool()使用了这种队列;3)SynchronousQueue;是一种不存储元素的阻塞队列,每个插入操作必须等另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,Executors.newCachedThreadPool使用了这个队列;(4)PriorityBlockingQueue,是一种具有优先权的阻塞队列,优先级大的任务可以先执行,用户由此可以控制任务的执行顺序。
- threadFactory 创建新线程时使用的工厂,threadFactory有两种选择:(1)DefaultThreadFactory,将创建一个同线程组且默认优先级的线程;(2)PrivilegedThreadFactory,使用访问权限创建一个权限控制的线程。ThreadPoolExecutor默认采用DefaultThreadFactory
- handler:超出线程范围和队列容量的任务的处理程序。handler有四个选择:(1)ThreadPoolExecutor.AbortPolicy(),将抛出RejectedExecutionException异常;(2)ThreadPoolExecutor.CallerRunsPolicy(),将重试添加当前的任务,重复调用execute()方法;(3)ThreadPoolExecutor.DiscardOldestPolicy(),将抛弃旧任务;(4)ThreadPoolExecutor.DiscardPolicy,将直接抛弃任务。ThreadPoolExecutor默认采用AbortPolicy。
-
-
线程池的实现原理
提交一个任务到线程池中,线程池的处理流程如下:
- 判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。
- 线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
- 判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
- 常用的线程池。
-
public static ExecutorService newSingleThreadExecutor()
创建仅有一个线程工作的线程池,相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么将创建有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
-
public static ExecutorService newCachedThreadPool()
创建一个缓存线程池,如果线程池的大小超过了任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又动态添加新线程来处理任务。此线程池没有对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)所能够创建的最大线程大小。
-
public static ExecutorService newFixedThreadPool(int nThreads)
创建指定大小的线程池。每次提交一个任务就创建一个线程,直到线程数量达到线程池的最大值。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
-
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
类似于newCachedThreadPool,创建一个缓存线程池,此线程池还支持定时以及周期性执行任务。
-