当前位置: 首页 > 后端技术 > Java

面试官:线程池、拒绝策略、阻塞队列有多少种?

时间:2023-04-02 01:48:25 Java

线程池工作原理ThreadPoolExecutor(intcorePoolSize,//核心线程数intmaximumPoolSize,//最大线程数longkeepAliveTime,//空闲线程存活时间TimeUnitunit,//存活时间单位BlockingQueueworkQueue,//阻塞队列RejectedExecutionHandlerhandler)//拒绝策略ThreadPoolExecutor线程池在创建时,里面没有工作线程,直到有任务进来(执行execute方法)才创建线程工作,工作原理如下遵循(即execute方法的运行原理):当线程池的execute方法被调用时,如果当前工作线程数小于核心线程数,则创建一个新的线程来执行任务;否则,任务被添加到阻塞队列。如果队列已满,则根据最大线程数创建额外的工作线程(核心线程数除外)执行任务;如果工作线程数达到最大线程数,则按照拒绝策略执行。如果存活时间到期,则只回收核心线程(maximumPoolSize-corePoolSize)以外的线程//3步://1.如果正在运行的线程数小于corePoolSize,请尝试使用给定的命令启动作为第一个线程一个新线程的任务。对addWorker的调用会自动检查runState和workerCount,这可以防止误报增加,并在不应该的时候返回false。//2.如果任务可以成功排队,那么我们还需要再次检查是否应该添加线程(因为自从上次检查以来现有的线程已经死亡)或者自进入该方法以来池已经关闭。所以我们重新检查状态并在必要时回滚队列停止,或者启动一个新线程(如果没有线程)。//3.如果我们不能将任务放入队列,那么我们尝试添加一个新的线程。如果它失败了,我们知道我们被关闭或饱和所以拒绝任务。publicvoidexecute(Runnablecommand){if(command==null)thrownewNullPointerException();intc=ctl.get();//第一步if(workerCountOf(c)workQueue);publicThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,TimeUnitunit,BlockingQueueworkQueue,ThreadFactorythreadFactory);publicThreadPoolSizePoolmax,AlivePoolSizeTimeUnitunit,BlockingQueueworkQueue,RejectedExecutionHandlerhandler);publicThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime,TimeUnitunit,BlockingQueueworkQueue,ThreadFactorythreadFactory,RejectedExecutionandHandler)参数含义:function}handler...}corePoolSize:核心池的大小。这个参数和后面介绍的线程池的实现原理有很大的关系。线程池创建后,默认情况下,线程池中没有线程,而是等待任务到来,然后再创建线程执行任务,除非调用了prestartAllCoreThreads()或prestartCoreThread()方法,从这些两种方法看名字就知道是pre-createdthreads的意思,也就是在没有任务到来之前创建corePoolSize个线程或者一个线程。默认情况下,创建线程池后,线程池中的线程数为0。当有任务到来时,会创建一个线程来执行该任务。当线程池中的线程数达到corePoolSize时,将到达的任务放入缓存队列;maximumPoolSize:线程池最大线程数,这个参数也是一个很重要的参数,它表示线程池最多可以创建多少个线程;keepAliveTime:表示在没有任务执行时线程最多能保持多久就会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时大于corePoolSize,如果一个线程空闲时间达到keepAliveTime,就会被终止,直到线程池中的线程数不超过corePoolSize。但是如果调用allowCoreThreadTimeOut(boolean)方法,当线程池线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池线程数为0;unit:参数keepAliveTime的时间单位,有7种Value,TimeUnit类中有7个静态属性:TimeUnit.DAYS;//天TimeUnit.HOURS;//小时TimeUnit.MINUTES;//分钟TimeUnit.SECONDS;//秒TimeUnit.MILLISECONDS;//毫秒时间单位。微秒;//微妙的TimeUnit.NANOSECONDS;//nanosecondworkQueue:一个阻塞队列,用于存放等待执行的任务。这个参数的选择也很重要,它会对线程池的运行过程产生重大影响。一般来说,这里的阻塞队列有以下几种选择:ArrayBlockingQueue;链接阻塞队列;同步队列;ArrayBlockingQueue和PriorityBlockingQueue用的比较少,一般用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。threadFactory:线程工厂,主要用于创建线程;handler:表示拒绝处理任务时的策略,有以下四个值:ThreadPoolExecutor.AbortPolicy:(默认)丢弃任务并抛出RejectedExecutionException。ThreadPoolExecutor.DiscardPolicy:同样丢弃任务,但不抛出异常。ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后再次尝试执行任务(重复这个过程)ThreadPoolExecutor.CallerRunsPolicy:任务由调用线程处理四种拒绝策略RejectedExecutionHandlerrejected=null;rejected=newThreadPoolExecutor.AbortPolicy();//默认,当队列满时,任务会抛出异常rejected=newThreadPoolExecutor.DiscardPolicy();//任务满时,队列不会抛出异常rejected=newThreadPoolExecutor.DiscardOldestPolicy();//删除先入队的任务,然后尝试再次入队rejected=newThreadPoolExecutor.CallerRunsPolicy();//如果加入线程池失败,主线程会自己执行任务;如果executor关闭(主线程结束),任务当然会被丢弃也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,比如对无法处理的任务进行日志记录或者持久化存储.三种阻塞队列BlockingQueueworkQueue=null;workQueue=newArrayBlockingQueue<>(5);//基于数组的先进先出队列,有界workQueue=newLinkedBlockingQueue<>();//基于链表的先进先出队列,无界workQueue=newSynchronousQueue<>();//无缓冲等待队列,无界来源:博客.csdn.net/AIGUO666666/article/details/103251145近期热点文章推荐:1.1000+道Java面试题及答案(2021最新版)2.别再满脑子if/else了,试试策略模式,好香!!3.操!Java中xx≠null的新语法是什么?4、SpringBoot2.5发布,深色模式太炸了!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!