线程池的优势:多线程
Android中的线程来源于Java中的Executor,实现类是ThreadPoolExecutor,ThreadPoolExecutor经过构造方法的一系列参数,来构成不一样配置的线程池。经常使用的构造方法有下面四个:ide
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
下面介绍上面说到的经常使用的四种队列,在这以前先根据上面的参数分析一下帮助理解:有核心线程、非核心线程、任务队列三个角色,他们能够根据当前配置,对每一个新来的任务作出处理(处理就是要么分配线程去执行任务,要么把任务存到任务队列里等待分配线程)。那么,三个角色能够设计以下:
有限个核心线程 + 任务队列(队列大小可配置)+ 无限个非核心线程
(确切的说是corePoolSize个核心线程,maximumPoolSize - corePoolSize个非核心线程)工具
不难理解,任务不少的时候,核心线程不够用了就存到任务队列里,队列存满了,就建立非核心线程执行任务(就像节假日客运站临时加车同样)。这样设计包含了两种极端状况,就是队列大小是0和队列无限大,因此具体设计以下三种状况:性能
这三种设计,就对应了workQueue参数的三种队列:SynchronousQueue, LinkedBlockingDeque, ArrayBlockingQueue.net
收到新任务时,直接交给线程处理,若是全部线程都在工做,那么新建线程来处理这个任务。若是将maximumPoolSize指定成Integer.MAX_VALUE,就是无限个线程。
(对应上面的第1种设计)线程
这个队列没有大小限制。当接收到新任务时,若是当前线程小于核心线程数,则新建核心线程处理任务。若是当前线程数等于核心线程数,则进入队列等待。因为队列没有大小限制,也就致使了 maximumPoolSize 的设定失效,由于这时最大线程数不会超过核心线程数。
(对应上面第2种设计)设计
能够限定队列长度,收到任务的时候,若是没有达到corePoolSize的值,则新建核心线程执行任务,若是达到了,入队等候。若是队列已满,则新建非核心线程执行任务。若是达到了maximumPoolSize,就会发生错误。
(对应上面第3种设计)code
队列内元素必须实现 Delayed 接口,这就意味着你传进去的任务必须先实现 Delayed 接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务。blog
现实中,队列不可能无限大,非核心线程不可能有无数个,那么上面几种队列就有超出线程总数的状况,这种状况只须要配置ThreadPoolExecutor的第7个参数RejectedExecutionHandler便可(能够翻到上面从新看下参数说明)。接口
下面介绍4种系统提供的配置好的线程池,固然,若是理解了上面的任务队列,本身配置出相同的线程池是很简单的。这4种线程池使用系统的工具类Executors来建立,以下:
//下面加了参数1的是由于没有无参数的重载方法。 Executors.newFixedThreadPool(1); Executors.newCachedThreadPool(); Executors.newScheduledThreadPool(1); Executors.newSingleThreadExecutor();
对应:有限个核心线程+任务队列(队列无限大) --> LinkedBlockingQueue
它的建立方法须要传入参数来指定核心线程数。功能特色很好理解,下面是艺术探索中对它的描述:
它是一种线程数量固定的线程池,当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭。当全部线程都处于活动状态时,新任务就会处于等待状态,直到有线程空闲出来。因为FixedThreadPool只有核心线程而且这些核心线程不会被回收,这意味着它可以更加快速地响应外界请求。经过newFixedThreadPool方法的源码能够发现FixedThreadPool中只有核心线程没有超时机制,另外任务队列也是没有大小限制的。
对应:有限个核心线程+无限个非核心线程 --> SynchronousQueue
它的核心线程数是0,因此它的建立方法不须要参数,下面是艺术探索中对它的描述:
它是一种线程数量不定的线程池,它只有非核心线程,而且最大线程数为Integer.MAX_VALUE。因为Integer.MAX_VALUE是一个很大的数,实际上就至关于最大线程数能够任意大。当线程池中的线程都处于活动状态时,线程池会建立新的线程来处理新任务,不然就会利用空闲线程来处理新任务。线程池中的空闲线程都有超时机制,超时时长是60秒,超过60秒闲置的线程就会被回收。和FixedThreadPool不一样的是,CachedThreadPool的任务队列其实至关于一个空集合,这将致使任何任务都会被当即执行。这类线程池比较适合执行大量的耗时较少的任务。当整个线程池处于闲置状态时,全部线程都会超时而被中止,这个时候CachedThreadPool中其实是没有任何线程的,它几乎是不占任何系统资源的。
对应:DelayQueue
它的建立方法须要参数来指定核心线程数,描述以下:
它的核心线程数是固定的,而非核心线程数是没有限制的。这个线程池主要用于执行定时任务和有固定周期的重复任务。
对应:有限个核心线程+任务队列(队列无限大) --> LinkedBlockingQueue
与FixedThreadPool的区别在于,SingleThreadExecutor只有一个核心线程,因此它的建立方法无需参数。描述以下:
这类线程池内部只有一个核心线程,它确保全部的任务都在同一个线程中按顺序执行。意义在于统一全部外界任务到一个线程中,这使得在这些任务之间不须要处理线程同步的问题。
最后是使用线程池的几个示例:
Runnable myRunnable = new Runnable() { @Override public void run() { SystemClock.sleep(2000); } }; //本身配置的线程池 ThreadPoolExecutor myExecutor = new ThreadPoolExecutor(2, 10, 5, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); //执行myRunnable任务 myExecutor.execute(myRunnable); //系统提供的线程池 ExecutorService fixedExecutor = Executors.newFixedThreadPool(1); //执行myRunnable任务 fixedExecutor.execute(myRunnable); //系统提供的线程池 ScheduledExecutorService sExecutor = Executors.newScheduledThreadPool(1); //2000ms后执行myRunnable sExecutor.schedule(myRunnable, 2000, TimeUnit.MILLISECONDS); //10ms后,每隔1000ms执行一次myRunnable sExecutor.scheduleAtFixedRate(myRunnable, 10, 1000, TimeUnit.MILLISECONDS);
《Android开发艺术探索》
Java多线程-线程池ThreadPoolExecutor构造方法和规则
线程池,这一篇或许就够了