其实JAVA架构之线程池是怎样工作的的问题并不复杂,但是又很多的朋友都不太了解为什么不建议用jdk自带线程池,因此呢,今天小编就来为大家分享JAVA架构之线程池是怎样工作的的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!
本文目录
一个spring项目定义多少个线程池
一个spring项目能够定义两个线程:SpringFrame的ThreadPoolTaskExecutor是辅助JDK的ThreadPoolExecutor的工具类,它将属性通过JavaBeans的命名规则提供出来,方便进行配置。1.ThreadPoolExecutorspring中的ThreadPoolTaskExecutor是借助于JDK
JAVA架构之线程池是怎样工作的
谢谢邀请!下面介绍一下线程池是怎样工作的?
ThreadPoolExecutor的类关系如下:
Executor是一个接口,它是Executor框架的基础,它将任务的提交与任务的执行分离开来。
ExecutorService接口继承了Executor,在其上做了一些shutdown()、submit()的扩展,可以说是真正的线程池接口;
AbstractExecutorService抽象类实现了ExecutorService接口中的大部分方法;
threadPoolExecutor是线程池的核心实现类,用来执行被提交的任务。
ScheduledExecutorService接口继承了ExecutorService接口,提供了带"周期执行"功能ExecutorService;
ScheduledThreadPoolExecutor是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令。ScheduledThreadPoolExecutor比Timer更灵活,功能更强大。
定义线程池
线程池的创建各个参数含义及流程如下:
1、corePoolSize
①线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize;
②如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行;
③如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。
2、maximumPoolSize
线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,
则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize
3、keepAliveTime
线程空闲的存活时间,即当线程没有任务执行时,继续存活的时间。
默认情况下,该参数只在线程数大于corePoolSize时才有用。
4、TimeUnit
keepAliveTime的时间单位。
5、WorkQueue
用于保存等待执行的任务的阻塞队列,一般来说,我们应该尽量使用有界队列,因为使用无界队列作为工作队列会对线程池做如下影响。
①当线程池中的线程数达到corePoolSize后,新任务将在无界队列中等待,因此线程池中的线程数不会超过corePoolSize。
②由于1,使用无界队列时maximumPoolSize将是一个无效参数。
③由于1和2,使用无界队列时keepAliveTime将是一个无效参数。
④更重要的,使用无界queue可能会耗尽系统资源,有界队列则有助于防止资源耗尽,同时即使使用有界队列,也要尽量控制队列的大小在一个合适的范围。
所以我们一般会使用,ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue。
6、threadfactory
创建线程的工厂,通过自定义的线程工厂可以给每个新建的线程设置一个具有识别度的线程名,
当然还可以更加自由的对线程做更多的设置,比如设置所有的线程为守护线程。
Executors静态工厂里默认的threadfactory,线程的命令规则时"pool-数字-thread-数字"
7、RejectedExecutionHandler拒绝策略
线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了4种策略:
①AbortPolicy:直接抛出异常,默认策略
②CallerRunsPolicy:用调用者所在的线程来执行任务
③DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务
④Discardpolicy:直接丢弃任务
当然也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理的任务。
线程池的工作机制
①如果当前运行的线程少于corePoolSize,则创建新线程来执行任务
②如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue
③如果无法将任务加入BlockingQueue(队列已满),则创建新的线程来处理任务。
④如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,
并调用RejectedExecutionHandler.rejectedExecution()方法。
java集合类中哪些是线程安全的
一些历史类的一般是线程安全的,例如:Vector,HashTable等在jdk升级后,出现了替代一些集合的类,ArrayList,HashMap等,一般都是线程不安全的。
在Java里如何减少线程上下文切换
对于单个java应用来说,减少线程上下文切换发生在多线程环境。题主问如何减少线程上下文切换,那么我们要环绕这几个问题讨论下。
一,你的应用是cpu密集型还是io密集型?
如果你的系统为cpu计算密集型,单个线程的cpu时间片越大越好,这就要求你对线程池的线程数做限制,防止过多线程对资源进行抢夺。
二,你给系统判定的并发上限是多少?
每个系统的性能都有上限,过大的负载,会造成性能低下,过小会浪费系统资源,所以需要结合业务得到一个最优值。
三,你的系统架构是否做了优化?
你的系统是否能横向扩展,尽量在网关,代理层进行流量转发,通过一定的负载均衡算法来降低单个系统的请求量。服务器的并发模型很重要,是一线程一请求,还是IO多路复用,还是异步模型,一线程一请求,在并发量大时,势必会造成线程切换频繁。
四,程序是否业务可以优化?
有些场景,优化业务,可以减少程序的处理性能,降低事务的处理时间,是否有cpu轮询,是否在复杂业务中大量使用CAS等等。
具体问题具体分析,优化是一条持久之路,没有最优,只有更优。
关于本次JAVA架构之线程池是怎样工作的和为什么不建议用jdk自带线程池的问题分享到这里就结束了,如果解决了您的问题,我们非常高兴。
声明:本文内容来自互联网不代表本站观点,转载请注明出处:https://bk.77788889.com/12/100983.html