并发编程体系-线程池

  1. 线程池的优点
    1. 降低资源消耗。通过重复利⽤已创建的线程降低线程创建和销毁造成的消耗。
    2. 提⾼响应速度。当任务到达时,任务可以不需要的等到线程创建就能⽴即执⾏。
    3. 提⾼线程的可管理性。线程是稀缺资源,如果⽆限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使⽤线程池可以进⾏统⼀的分配,调优和监控。
  2. 使用execute()和submit()方法 的区别
    1. execute() ⽅法⽤于提交不需要返回值的任务,所以⽆法判断任务是否被线程池执⾏成功与否;
    2. submit() ⽅法⽤于提交需要返回值的任务。线程池会返回⼀个 Future 类型的对象,通过这个 Future 对象可以判断任务是否执⾏成功,并且可以通过 Future 的 get() ⽅法来获取返回值, get() ⽅法会阻塞当前线程直到任务完成,。
  3. 线程池的实现原理
    在这里插入图片描述
    1. 判断线程池正在执行的线程数是否达到了核心线程数,如果没有则创建一个线程来执行任务。如果达到核心线程数,则进入下一个流程
    2. 判断当前工作队列是否已经满了,如果没有满则将新提交的任务存储在这个工作队列里,如果满了就进入下一个流程
    3. 判断当前线程池的线程数是否达到maximumPoolSize,如果没有,则创建一个救急线程来处理,如果满了就执行饱和策略
  4. ThreadPoolExecutor
    1. ThreadPoolExecutor构造方法:
      在这里插入图片描述
  5. ThreadPoolExecutor的参数
    1. corePoolSize。线程池的基本大小,核⼼线程数线程数定义了最⼩可以同时运⾏的线程数量。
    2. maximumPoolSize。线程池允许创建的最大数量。如果队列满了,但创建的线程数小于maximumPoolSize,则线程池会创建新的线程执行任务,这个的前提是任务队列是有界的!!,maximumPoolSize会有一定的存活时间。
    3. workQueue。任务队列,当线程执行的任务到达corePoolSize大小的时候,剩下的任务到来会先进入任务队列等待。可以选择如下几种任务队列:
    ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO的原则对元素进行排序
    LinkedBlockingQueue:基于链表结构的阻塞队列,按FIFO原则
    PriorityBlockingQueue:具有优先级的无限阻塞队列
    SynchronousQueue:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用溢出操作,否则就一直处于阻塞状态。
    4. KeepAliveTime。救急线程在空闲状态下的等待时间,超过这个时间就销毁。
    5. TimeUnit。时间单位。
    6. ThreadFactory。用来设置线程的工厂。
    7. RejectedExecutionHandler(饱和策略)。当队列和线程池都满了,对于接下来要到达的任务必须采取一种策略来处理提交。默认使用的是AbortPolicy,在无法接受新任务时抛出异常。
    在这里插入图片描述
    1. AbortPolicy。直接抛出异常。
    2. CallerRunsPolicy。让调用者用自己的线程来执行任务
    3. DiscardOldestPolicy。丢弃队列中最早未处理的一个任务并执行当前任务。
    4. DiscardPolicy。不处理直接丢掉
  6. shutdown和shutdownNow的比较
    1.shutdown不会接受新的任务但是会执行完已提交的任务。
    2. shutdownNow,不会接受新的任务,且返回等待执行任务的列表,并用interrupt的方式打断线程

Executors

  1. FixedThreadPoolExecutorService pool=Executors.newFixedThreadPool(int n)固定大小的线程池,如果线程不空闲,就进入等待队列,等待队列是无限队列。LinkedBlockingQueue

  2. SingleThreadExecutorExecutorService pool=Executors.newSingleThreadExecutor()单线程的线程池,保证各个任务按顺序执行.LinkedBlockingQueue

  3. CachedThreadPool.ExecutorService pool=Executors.newCachedThreadPool()可根据实际情况调整线程数量的线程池,核心线程数是 0, 最大线程数是 Integer.MAX_VALUE,救急线程的空闲生存时间是 60s。SynchronousQueue

  4. 怎么创建合适的线程
    1. 如果线程数过少导致程序不能充分利用系统资源,会导致线程池饥饿问题(因为线程太少导致任务无法处理)
    2. 如果线程数过多会导致更多的线程上下文切换,占用更多的内存
    3. CPU密集型运算:应该配置尽可能小的线程(CPU密集型任务提高CPU利用率,少的线程避免线程空闲)
    在这里插入图片描述
    4. I/O密集型运算:应该配置尽可能多的线程。(I/O密集型任务线程并不是一直在执行任务)
    在这里插入图片描述

Fork/Join线程池

Fork/Join 体现的是一种分治思想,将大任务拆分成若干个小任务,最终汇总每个小任务的结果得到大任务的结果,Fork/Join 默认会创建与 cpu 核心数大小相同的线程池。

  1. fork方法的实现原理:当调用fork方法时,程序会调用PushTask异步执行这个任务然后立即返回结果,PushTask方法会把当前任务存放在
    数组队列,然后去唤醒或者创建一个工作线程执行任务
  2. join方法的实现原理:join方法主要作用是阻塞当前线程并等待获取返回结果。首先查看任务状态,看任务是否被执行完成,如果执行完成就返回任务状态,没执行完就从任务数组中提取任务并执行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值