Java并发编程-精通篇(线程池) 心已赠人 2022-03-19 11:53 166阅读 0赞 # 1. 线程池原理 # ## 线程池的创建 ## public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) corePoolSize:线程池核心线程数量 maximumPoolSize:线程池最大线程数量 keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间 unit:存活时间的单位 workQueue:存放任务的队列 handler:超出线程范围和队列容量的任务的处理程序 ## 线程池的实现原理 ## ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI0NDkzNjM_size_16_color_FFFFFF_t_70] 提交一个任务到线程池中,线程池的处理流程如下: 1、如果当前运行的线程少于corePoolSize,则创建新线程来执行任务。 2、如果运行的线程等于或多于corePoolSize,则将任务加入BlockingQueue。 3、如果无法将任务加入BlockingQueue(队列已满),则在非corePool中创建新的线程来处理任务。 4、如果创建新线程将使当前运行的线程超出maximumPoolSize,任务将被拒绝,并调用RejectedExecutionHandler.rejectedExecution()方法。 # 2. 常用的线程池 # Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 ## CachedThreadPool ## public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } corePoolSize:0 maximumPoolSize: Integer.MAX\_VALUE keepAliverTime:60L unit:TimeUnit.SECONDS workQueue:new SynchronousQueue() 特点: 从以上参数可以看出,初始化一个核心线程池为0的线程池,线程池最大线程数量为无穷大。阻塞队列是个长度为空的阻塞队列。因此对照线程池的执行过程,可以发现: 1.如果工作线程执行时间较短,则线程池内只需要保留非常少的工作线程即可满足需求 2.一旦工作线程在执行时间较长,线程池将不断创建新的工作线程,可能会占用较多的系统资源 3. 适用于任务耗时短,并发数量大的情况 ## FixedThreadPool ## public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } corePoolSize:nThreads maximumPoolSize: nThreads keepAliverTime:0L unit:TimeUnit.MILLISECONDS workQueue:new LinkedBlockingQueue() 特点: 1. 线程池核心线程数和最大线程数相等 2. 线程池内工作线程用完即释放 3. 等待线程放入阻塞队列,且队列无界(直到超出系统内存) 4. 适用于高并发场景下控制性能 ## ScheduledThreadPool ## public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue()); } corePoolSize:corePoolSize maximumPoolSize: Integer.MAX\_VALUE keepAliverTime:DEFAULT\_KEEPALIVE\_MILLIS, MILLISECONDS(10L) unit:MILLISECONDS(毫秒) workQueue:new DelayedWorkQueue() ScheduledThreadPool 在执行时可以指定执行的计划时间。 1. 每隔固定的时间执行 public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) 1. 在initialDelay时间开始第一次执行,之后在间隔时间period执行。即上一个线程开始时间与下一个线程开始时间的间隔为period。如果线程执行时间超过了peroid,则下个线程将在上个线程执行完之后立即执行。 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) 1. 在initialDelay时间开始第一次执行,之后每隔间隔时间period执行。即上一个线程结束时间与下一个线程开始时间的间隔为delay public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) ## SingleThreadExecutor ## public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } corePoolSize:1 maximumPoolSize: 1 keepAliverTime:0L unit:TimeUnit.MILLISECONDS workQueue:new LinkedBlockingQueue() 只有一个线程执行任务,多余的任务将被放到阻塞队列(无界)等待,适用于并发数不高,但是有一定顺序要求的场景 # 3. 拒绝策略 # 当队列和线程池都满了,说明线程池处于饱和状态,那么必须对新提交的任务采用一种特殊的策略来进行处理。这个策略默认配置是AbortPolicy,表示无法处理新的任务而抛出异常。JAVA提供了4中策略: 1、AbortPolicy:直接抛出异常 2、CallerRunsPolicy:只用调用所在的线程运行任务 3、DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。 4、DiscardPolicy:不处理,丢弃掉。 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI0NDkzNjM_size_16_color_FFFFFF_t_70]: /images/20220319/de098acc2b7c4cdeb0b1a8cc6d3273c3.png
还没有评论,来说两句吧...