并发编程-线程池(五)线程池为什么不允许使用Executors创建
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了并发编程-线程池(五)线程池为什么不允许使用Executors创建,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4268字,纯文字阅读大概需要7分钟。
内容图文
一、Executors 线程池创建工具【1】
1、Executors.newCachedThreadPool();
说明:
创建的线程池核心线程0 , 最大线程是Integer.MaxValue。 线程空闲存活时间1分钟。 默认异常拒绝策略,使用SynchronousQueue队
特点:
每次添加任务如果没有空闲线程就会新建一个线程去执行。
SynchronousQueue是阻塞队列,加入任务的线程会阻塞住,直到其它线程从中取走任务才会结束阻塞
线程创建上限近乎无限
适用场景:
所以它适用于任务加入比较稳当且加入间隔短的场景
实现:
new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue());
缺点:
任务队列是SynchronousQueue,线程池对任务来着不拒,线程不够用就创建一个线程。
如果同一时刻应用的来了大量的任务, 这个线程池很容易就创建过多的线程, 容易导致应用卡顿或者直接OOM
2、Executors.newFixedThreadPool(int);
说明:
核心线程和最大线程数是你传入的参数。 其他参数和 Executors.newSingleThreadExecutor一样
实现:
new ThreadPoolExecutor(nThreads, nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue());
缺点:
这个定死了线程数量, 所以线程数量是不会超出的,但是它的任务队列是无界的LinkedBlockingQueue
加进来的任务处理不过来就会存入任务队列中, 并且无限制的存入队列,很容易导致OOM。
3、Executors.newSingleThreadExecutor();
说明:
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照顺序执行。
特点:
只有一个线程
近乎可以接收无限任务的队列, 可以堆积大量任务
适用于任务持续加入但是任务数并不多的场景
实现:
new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue())
缺点:
任务队列和上面一样, 没有限制, 很容易就使用不当导致OOM
4、Executors.newScheduledThreadPool(int);
说明:
创建一个定长线程池,支持定时及周期性任务执行。
特点:
核心线程是传入的参数,最大线程是int上线, 默认存活时间是10毫秒, 任务队列使用自己实现的DelayedWorkQueue, 拒绝策略异常策略
加入任务的时候,会把任务和定时时间构建一个RunnableScheduledFuture对象,再把这个对象放入DelayedWorkQueue队列中,
DelayedWorkQueue是一个有序队列, 他会根据内部的RunnableScheduledFuture的运行时间排序内部对象。
任务加入后就会启动一个线程。 这个线程会从DelayedWorkQueue中获取一个任务。
DelayedWorkQueue内部是按照时间从前完后获取任务的。如果任务的中的时间还没有到。 获取的就是null。 获取任务结束,线程会休眠10毫秒。所以这个定时任务的执行最小间隔是10毫秒的。
内部实现:
new ScheduledThreadPoolExecutor(corePoolSize)
缺点:
这个是定时任务的线程池, 没有定义线程创建数量的上线, 同时任务队列也没有定义上限, 如果前一次定时任务还没有完成, 后一个定时任务的运行时间到了, 它也会运行, 线程不够就创建。
这样如果定时任务运行的时间过长, 就会导致前后两个定时任务同时执行,如果他们之间有锁,还有可能出现死锁。
二、线程池推荐创建方式
1、 方式一:引入 commons-lang3包
ScheduledExecutorService executorService =
new ScheduledThreadPoolExecutor(1,new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
2、方式二:引入:com.google.guava包
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() .setNameFormat("demo-pool-%d").build(); //Common Thread Pool ExecutorService pool = new ThreadPoolExecutor(5, 200, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); pool.execute(()-> System.out.println(Thread.currentThread().getName())); pool.shutdown();//gracefully shutdown
3、方式三:spring配置线程池方式:自定义线程工厂bean需要实现ThreadFactory,可参考该接口的其它默认实现类,使用方式直接注入bean
调用execute(Runnable task)方法即可
<bean id="userThreadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="10" /> <property name="maxPoolSize" value="100" /> <property name="queueCapacity" value="2000" /> <property name="threadFactory" value= threadFactory /> <property name="rejectedExecutionHandler"> <ref local="rejectedExecutionHandler" /> </property> </bean> //in code userThreadPool.execute(thread);
三、ThreadPoolExecutor 使用
https://www.cnblogs.com/dafanjoy/p/9729358.html
---------------------------------------------------------------------------------------------------------------------
【3】https://www.cnblogs.com/dafanjoy/p/9729358.html
内容总结
以上是互联网集市为您收集整理的并发编程-线程池(五)线程池为什么不允许使用Executors创建全部内容,希望文章能够帮你解决并发编程-线程池(五)线程池为什么不允许使用Executors创建所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。