使用阻塞队列就无需考虑同步和线程间通信的问题 。
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(); } } } }}
文章插图
三、线程池在编程中经常会使用线程来异步处理任务,但是每个线程的创建和销毁都需要一定的 开销 。如果每次执行一个任务都需要打开一个新线程去执行,则这些线程的创建和销毁 将消耗大量的资源,并且线程都是各自为政的,很难对其进行控制,更何况还有一堆的 线程在执行,这时就需要线程池来对线程进行管理,在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.1.提交任务后,线程池先判断线程数是否达到了核心线程数(corepoolSize)
如果还没有达到核心线程数,则创建核心线程处理任务,否则执行下一步 。
2.2.线程池判断任务队列是否满了,如果没满,将任务加入任务队列,否则执行
下一步 。
2.3.线程池判断线程数是否达到最大线程数,如果未达到,则创建非核心线程处理任务,
否则就执行饱和策略,默认会抛出RejectedExecutionExeception异常 。
文章插图
通过线程池的执行示意图我们可以看出,如果我们执行ThreadPoolExecutor的execute方法,
会遇到各种情况
- 如果线程池中的线程数没有达到核心线程数,则创建核心线程执行任务 。
- 如果线程池中的线程数大于或等于核心线程数,则加入任务队列,线程池中的空闲线程会不断的从任务队列中取任务执行 。
- 如果任务队列满了,并且线程数没有达到最大线程数,则创建非核心线程去处理任务 。
推荐阅读
- 深扒七大自媒体平台:哪个吸引流量多,哪个赚钱最容易?
- 如何控制Java多线程分布到不同的CPU核上去?
- 富贵包能不能打溶脂针 富贵包吸脂后多久有效果
- 开淘宝店卖虚拟产品需要多少钱 开虚拟网店需要多少钱
- 微软|在微软搞黄的70多个项目里 竟然还有个厕所
- 幽门螺旋杆菌为什么是致癌物,幽门螺旋杆菌致癌物有多可怕
- 为什么女生剪短发发尾会翘,女生剪短发翘多久会恢复
- 2022东莞回南天一般在几月份,东莞回南天一般持续多久
- 淘宝开店一年赚多少钱 现在开淘宝店一年可以赚多少
- 世界上存活最久的物种 世界上已经灭绝的生物有多少种