zoukankan      html  css  js  c++  java
  • java线程池

    1、为什么用线程池

    1)降低资源消耗,线程是稀缺资源,所以反复的创建销毁,是非常消耗资源的

    2) 提高响应率 ,大量请求高并发,多线程速度快

    3)提高线程的可管理性,线程池进行管理和监控

    2、线程池继承实现关系

    public class ThreadPoolExecutor extends AbstractExecutorService
    public abstract class AbstractExecutorService implements ExecutorService
    public interface ExecutorService extends Executor
    public interface Executor{
    void execute(Runnable command);
    }
    ExecutorService里面放的是管理线程池的方法
    Executors 
    放的是4个创建线程池的方法
    第一个是newSingleThreadPoolExcutor 定义一个线程进行使用串行话
    第二个是newFixsThreadPoolExcutor定义n个线程进行使用,空闲线程会一直保留
    第三个是newCacheThreadPoolExcutor 不用指定线程数,空闲线程不会创建
    第四个是 newSheduelThreadPoolExcutor 创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求
    都是使用的execute方法进行调用线程池
    问什么不建议使用excutors静态工厂创建线程池
    因为
    newSingleThreadPoolExcutor和
    newFixsThreadPoolExcutor他们使用的LinkedBlockingQueue这个队列,他是都是有长度限制的integer.max,当超过了就会报内存溢出的
    newCacheThreadPoolExcutor和
    newSheduelThreadPoolExcutor 他们允许创建的线程数最多是
    integer.maxValue 2^31 超过了就会报内存溢出的
    所以建议使用
    new ThreadPoolExecutor (
    核心线程数,
    最大线程数,
    线程数量超过corePoolSize,空闲线程的最大超时时间
    时间单位,
    工作队列,
    用来保存等待被执行的任务的阻塞队列,且任务必须实现Runable接口,在JDK中提供了如下阻塞队列:
    1、ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务;
    2、LinkedBlockingQuene:基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQuene;
    3、SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene;
    4、priorityBlockingQuene:具有优先级的无界阻塞队列;
    工厂类,
    拒绝策略
    线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,线程池提供了4种策略:
    1、AbortPolicy:直接抛出异常,默认策略;
    2、CallerRunsPolicy:用调用者所在的线程来执行任务;
    3、DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
    4、DiscardPolicy:直接丢弃任务;

    线程池底层逻辑

    1、判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。

    2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。

    3、判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

    假如提交到线程池中的任务,IO耗时占比是90%,计算耗时占比10%,忽略提交到线程池中的任务数量,在4C8G的机器上,理想情况下线程池中创建多少个线程是最优的

    一般平时只埋头写CURD的候选人,难以计算出来,当然也遇到了不少能算出来结果来的,线程数=(1/0.1) * 4 = 40假如e有一类cpu密集性的任务,没有IO操作,日常的时候只有1个任务,流量高峰会有50个任务,4C8G的机器上,使用的线程池,如何设置corePoolSize, maxPoolSize以及BlockingQueue的大小

    很显然,日常只需要一个线程,那么corePoolSize=1,而高峰时候,虽然任务有50个,但是只是4C的机器,对于cpu密集型任务,4个线程是最优的,因此理想情况下maxCorePoolSize=4,最后再看看队列,因为队列满了,max才会被创建,而我们需要让max快速被创建出来,又不会出现任务拒绝,因此,可将队列大小设置成46,那么线程池的行为如下:

    • 提交第一个任务,创建出core,1个线程
    • 提交第二个到第47个任务时,这些任务进入到队列中,此时队列已满
    • 提交第48个任务到第50个任务时,创建出max,此时一共有4个线程
    • 4个线程同时将队列里的46个任务消费完
    • 一段时间后,max - core数量的线程销毁,即销毁3个线程,还剩下一个线程
     


    想要体面生活,又觉得打拼辛苦;想要健康身体,又无法坚持运动。人最失败的,莫过于对自己不负责任,连答应自己的事都办不到,又何必抱怨这个世界都和你作对?人生的道理很简单,你想要什么,就去付出足够的努力。
  • 相关阅读:
    sudo killall -9 php
    php 读取Excel内容时 对时间的值进行格式化处理
    执行Git命令时出现各种 SSL certificate problem 的解决办法
    git 强制拉取更新,本地修改
    PHP:如何合并多维数组中的子数组
    hibernate.validator 与 jackson
    jackson实体转json时 为NULL不参加序列化的汇总
    application.yml 增加数据库连接,重启日志卡死
    logback学习
    注解@Slf4j
  • 原文地址:https://www.cnblogs.com/potentPrince/p/12574190.html
Copyright © 2011-2022 走看看