Android多线程编程之详解:阻塞队列+线程池( 二 )

使用阻塞队列就无需考虑同步和线程间通信的问题 。
public class VolatikeDemo { private int queueSize=10; private ArrayBlockingQueue<Integer> queue=new ArrayBlockingQueue<>(queueSize); public static void main(String args[]){ VolatikeDemo demo=new VolatikeDemo(); Consumer consumer=demo.new Consumer(); Producer producer=demo.new Producer(); consumer.start(); producer.start(); } class Consumer extends Thread{ @Override public void run() { while(true){ try { int res=queue.take(); System.out.println(res); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Producer extends Thread{ @Override public void run() { while(true){ try { this.sleep(200); queue.put(1); } catch (InterruptedException e) { e.printStackTrace(); } } } }}

Android多线程编程之详解:阻塞队列+线程池

文章插图
 
三、线程池在编程中经常会使用线程来异步处理任务,但是每个线程的创建和销毁都需要一定的 开销 。如果每次执行一个任务都需要打开一个新线程去执行,则这些线程的创建和销毁 将消耗大量的资源,并且线程都是各自为政的,很难对其进行控制,更何况还有一堆的 线程在执行,这时就需要线程池来对线程进行管理,在java 1.5中提供了Executor框架用于 把任务的提交和执行解耦,任务的提交交给Runnable或者Callable,而Executor框架用来 处理任务,Executor框架中的核心成员就是ThreadPoolExecutor,他是线程池的核心类 。
1.ThreadPoolExecutor
【Android多线程编程之详解:阻塞队列+线程池】可以通过创建ThreadPoolExecutor来创建一个线程池,ThreadPoolExecutor类一共有四个构造方法
其中拥有最多参数的构造方法:
ThreadPoolExecutor poolExecutor=new ThreadPoolExecutor(?,?,?,?,?);
  • corePoolSize:核心线程数,默认情况下线程池是空的,只有任务提交是才会线程,如果当前运行的线程数少于corePoolSize,则创建新线程来处理任务,如果等于或者多余corepoolsize则不会创建新线程,如果调用prestartAllcoreThread()方法:线程池会提前创建并启动所有的核心线程来等待任务 。
  • maximumPoolSize:线程池允许创建的最大线程数,如果任务队列满了,并且线程数小于maximumPoolSize,则线程仍会创建新线程来处理任务 。
  • keepAliveTime:非核心线程闲置的超时时间,超过这个时间则回收,如果任务很多,并且每个任务的执行时间的时间很短,则可以调大keepAliveTime来提高线程的利用率 。
  • TimeUnit:keepAliveTime参数的时间单位,可选的单位有天,小时,分钟,秒,毫秒等
  • workQueue:任务队列,如果当前线程数大与corePoolSize则将任务添加到此任务队列中,该任务队列是BlockingQuenu类型的,也就是阻塞队列
  • ThreadFactory:线程工厂,可以线程工厂给每个创建出来的线程池设置名字,一般情况下无需要设置此参数
  • RejectedExecutionHandler:饱和策略,这是当任务队列和线程池都满了时所采取的应对策略默认是无法处理新任务(AbordPolicy)并抛出RejectedExecutionException异常,此外还有三种策略,分别如下:1.CallersRunsPolicy:用调查者所在的线程来处理任务,此策略提供简单的反馈控制机制,能够减缓新任务的提交速度(简言之,降低提交速度)
  • DiscardPolicy:不能执行的任务,并将该任务删除
  • DiscardOldestPolicy:丢弃队列最近的任务,并执行当前的任务 。
2.线程池的处理流程和原理
Android多线程编程之详解:阻塞队列+线程池

文章插图
 
2.1.提交任务后,线程池先判断线程数是否达到了核心线程数(corepoolSize)
如果还没有达到核心线程数,则创建核心线程处理任务,否则执行下一步 。
2.2.线程池判断任务队列是否满了,如果没满,将任务加入任务队列,否则执行
下一步 。
2.3.线程池判断线程数是否达到最大线程数,如果未达到,则创建非核心线程处理任务,
否则就执行饱和策略,默认会抛出RejectedExecutionExeception异常 。
Android多线程编程之详解:阻塞队列+线程池

文章插图
 
通过线程池的执行示意图我们可以看出,如果我们执行ThreadPoolExecutor的execute方法,
会遇到各种情况