首页 > 编程知识 正文

java实现线程池,java线程池等待原理

时间:2023-05-05 06:49:52 阅读:151027 作者:1890

java线程池的原理和使用方法1、使用线程池的理由2、线程池的几个重要参数3、线程池的使用方法1 .体系结构说明2、编码实现4、线程池的基本操作原理5、工作中线程池

一.为什么要使用线程池

1 .线程池主要负责控制要执行的线程数量。 在处理过程中对任务进行排队,并在创建线程后启动这些任务。 如果线程数超过最大值,则超出最大值的线程将排队等待,等待其他线程运行,然后从队列中取出任务并执行

2 .线程池的主要特征

线程复用、控制最大并发行数、管理线程

通过减少资源消耗和重用创建的线程,减少创建和销毁线程所消耗的资源并提高响应速度。 任务到达时,任务可以立即执行提高线程的客观理想,而无需等待线程的创建。 线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性。 使用线程池进行统一分配,2、线程池的几个重要参数publicthreadpoolexecutor (intcorepolsize,int maximumPoolSize,long keepalive BlockingQueueRunnable workQueue,ThreadFactory threadFactory,rejectedexecutionhandlerhandler

创建线程池后,在请求任务到来时,将请求任务调度为池中的线程执行。 线程池线程数达到corePoolSize后,将到达的任务排入缓存队列。 2.maximumPoolSize :可以同时在线程池中运行的最大线程数必须至少为1

3.keepAliveTime :剩余空闲线程的生存时间

如果当前线程池数量超过corePoolSize,当空闲时间达到keepAliveTime值时,多余的空闲线程将以4.unit:keepAliveTime为单位丢弃,直到只剩下corePoolSize个线程

5 .工作队列:任务队列,已提交但尚未运行的任务

6.threadFactory :表示生成线程池中的工作线程的线程工厂,为了创建线程通常只需使用默认的

7.handler )拒绝策略是一种指示当队列已满且工作线程超过线程池的最大线程数(maximumPoolSize )时如何拒绝请求执行的runable的策略

关于拒绝策略的介绍

1 .拒绝策略队列也已满,无法填充新任务,同时线程池中的max线程也已完成,无法继续服务新任务。 在这种情况下,我们应该拒绝合理处理这个问题的战略机制。

2.JDK中的内置拒绝策略

AbortPolicy (默认) ) ) ) ) ) ) ) ) )。

直接抛出RejectedExecutionException异常以阻止系统正常运行的CallerRunsPolicy

调用者运行“协调机制”,将某些任务回滚到调用者,以减少新任务的流量,而不是放弃任务或抛出异常

放弃在队列中等待最长时间的任务,将当前任务添加到队列中,然后尝试重新发送当前任务DiscardPolicy

直接放弃任务,不做任何处理,也不放弃异常。 在允许任务丢失的情况下,这是最好的方案3,线程池的使用方法1 .模式显示Java的线程池是在Executor框架中实现的,在该框架中使用

执行程序、执行程序、执行服务、thread pool执行程序

2 .有五种编码实现。 executors.newscheduledthreadpool ()带有时间调度。 java8新推出了executors.newworkstealingpool ),将当前计算机上可用的处理器用作他的并行级别

三种重要的线程池

executors.newfixedthreadpool (int )。

创建固定长度线程池以控制最大线程并发次数,超出的线程将排队等待。 newFixedThreadPool创建的线程池corePoolSize和maximumPoolSize的值相同,他使用的是LinkedBlockingQueue的应用场景。 是执行长期任务、性能非常高的executors.newsinglethreadexececeue

创建单线程语言线程池。 他只在唯一的工作线程上执行任务,并确保所有任务都按指定顺序执行。 newSingleThreadExecutor将corePoolSize和maximumPoolSize设定为1,并使用LinkedBlockingQueue应用场景。 任一个

务一个任务执行的场景

Executors.newCachedThreadPool()

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲县城,若无可回收,则新建线程。newCachedThreadPool将corePoolSize设置为0,将maximumPoolSize设置为Integer.MAX_VALUE,使用的SynchronousQueue,也就是说来了任务就创建线程运行,当县城空闲超过60s,就销毁线程适用场景:执行很多短期异步的小程序或负载较轻的服务器 四、线程池底层工作原理

原理图

流程
1.在创建了线程池之后,等待提交过来的 人物请求。

2.当调用execute()方法添加一个请求任务时,线程池会做出如下判断
(1)如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务;
(2)如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列;
(3)如果此时队列满了且运行的线程数小于maximumPoolSize,那么还是要创建非核心线程立刻运行此任务
(4)如果队列满了且正在运行的线程数量大于或等于maxmumPoolSize,那么启动饱和拒绝策略来执行

3.当一个线程完成任务时,它会从队列中取下一个任务来执行

4.当一个线程无事可做超过一定的时间(keepAliveTime)时,线程池会判断:如果当前运行的线程数大于corePoolSize,那么这个线程会被停掉;所以线程池的所有任务完成后它最大会收缩到corePoolSize的大小

五、工作中如何使用线程池 1.选择创建线程池的方法

上面提到的三个重要的线程池都不用,生产上只能用自定义的

原因:

线程池不允许使用Executors创建,试试通过ThreadPoolExecutor的方式,规避资源耗尽风险FixedThreadPool和SingleThreadPool允许请求队列长度为Integer.MAX_VALUE,可能会堆积大量请求;CachedThreadPool和ScheduledThreadPool允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量线程,导致OOM(内存溢出) 2.合理配置线程池参数

CPU密集型

CPU密集的意思是该任务需要大量的运算,而没有阻塞,CPU一直全速运行CPU密集任务只有在真正多核CPU上才可能得到加速(通过多线程)而在单核CPU上,无论你开几个模拟的多线程该任务都不可能得到加速,因为CPU总的运算能力就那些CPU密集型任务配置尽可能少的线程数量一般公式:CPU核数+1个线程的线程池

IO密集型

由于IO密集型任务线程并不是一直在执行任务,则应配置经可能多的线程,如CPU核数 * 2IO密集型,即该任务需要大量的IO,即大量的阻塞。在单线程上运行IO密集型的任务会导致浪费大量的 CPU运算能力浪费在等待。所以在IO密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速主要就是利用了被浪费掉的阻塞时间。IO密集型时,大部分线程都阻塞,故需要多配置线程数参考公式:
CPU核数/(1-阻塞系数) 阻塞系数在0.8~0.9之间
八核CPU:8/(1-0,9)=80 3.示例代码 package com.jian8.juc.thread;import java.util.concurrent.*;public class MyThreadPoolDemo { public static void main(String[] args) {// Executors.newFixedThreadPool(5);// Executors.newSingleThreadExecutor();// Executors.newCachedThreadPool(); ExecutorService threadPool = new ThreadPoolExecutor( 3, 5, 1L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy()); //拒绝策略// new ThreadPoolExecutor.AbortPolicy();// new ThreadPoolExecutor.CallerRunsPolicy();// new ThreadPoolExecutor.DiscardOldestPolicy();// new ThreadPoolExecutor.DiscardPolicy(); try { for (int i = 1; i <= 10; i++) { threadPool.execute(() -> { System.out.println(Thread.currentThread().getName() + "t办理业务"); }); } } catch (Exception e) { e.printStackTrace(); } finally { threadPool.shutdown(); } }}

运行结果:

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。