线程的理解

线程的内存存放的位置:

  创建的线程 分配的内存空间就是到堆内存中,当线程使用对象是全部都去堆内存中取数据。

线程池的四中拒绝策略:

  在线程中定义要实现的ThreadPoolExecutor 类, ThreadPoolExecutor中 默认的 拒绝策略是  AbortPolicy

corePoolSize 线程池核心线程数量,
maximumPoolSize 线程池允许的最大线程数量,
keepAliveTime 空闲线程的存活时间,
unit 时间单位,
workQueue 等待队列,
threadFactory 线程工厂,
handler 拒绝处理器。
RejectedExecutionHandler 是一个接口,定义了线程池拒绝线程需要执行的方法。

public
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {

第二种:

CallerRunsPolicy,顾名思义,就是调用者执行,指的是主线程提交一个任务给线程池,线程池很忙拒绝了,如果线程池采用的是此种策略,则交由主线程自己去完成。

public
static class CallerRunsPolicy implements RejectedExecutionHandler { public CallerRunsPolicy() { } oid rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); } } }

第三种:

DiscardPolicy,直接丢弃,不做任何处理

public
static class DiscardPolicy implements RejectedExecutionHandler { public DiscardPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { } }

第四种:

DiscardOldestPolicy,这种策略指的是丢弃等待队列里头节点的任务,执行刚提交的任务。
线程池拒绝的时机,我们可以看一下execute方法

public
static class DiscardOldestPolicy implements RejectedExecutionHandler { public DiscardOldestPolicy() { } public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { e.getQueue().poll(); e.execute(r); } } }


public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }

主要分3步:

  1.如果线程池的工作线程小于设置的核心线程数,则调用addWorker增加一个工作线程,Worker为ThreadPoolExecutor定义的工作线程,继承于AbstractQueuedSynchronizer(implementing blocking locks);

  2.如果线程可以成功加入等待队列,则做一次double-check,即加入了队列后再次检查线程池运行状态,如果状态异常则从队列里删除,执行拒绝策略,否则如果判断没有工作线程了,则新加一个工作线程;

  3.如果等待队列已经满了,则尝试新加一个工作线程,如果失败执行拒绝策略。


这里简单从源码角度分析了线程池默认实现的四种拒绝策略,当然我们也可以通过实现RejectedExecutionHandler接口自定义拒绝策略处理器,然后在定义线程池的时候指定一下就可以了。

拒绝策略场景分析

  AbortPolicy

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

A handler for rejected tasks that throws a {@code RejectedExecutionException}.

这是线程池默认的拒绝策略,在任务不能再提交的时候,抛出异常,及时反馈程序运行状态。如果是比较关键的业务,推荐使用此拒绝策略,这样子在系统不能承载更大的并发量的时候,能够及时的通过异常发现。

DiscardPolicy

  

ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。如果线程队列已满,则后续提交的任务都会被丢弃,且是静默丢弃。

A handler for rejected tasks that silently discards therejected task.

 使用此策略,可能会使我们无法发现系统的异常状态。建议是一些无关紧要的业务采用此策略。例如,本人的博客网站统计阅读量就是采用的这种拒绝策略。

DiscardOldestPolicy

ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务。

A handler for rejected tasks that discards the oldest unhandled request and then retries {@code execute}, unless the executor is shut down, in which case the task is discarded.

此拒绝策略,是一种喜新厌旧的拒绝策略。是否要采用此种拒绝策略,还得根据实际业务是否允许丢弃老任务来认真衡量。

CallerRunsPolicy

ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

A handler for rejected tasks that runs the rejected task directly in the calling thread of the {@code execute} method, unless the executor has been shut down, in which case the task is discarded.

如果任务被拒绝了,则由调用线程(提交任务的线程)直接执行此任务,我们可以通过代码来验证这一点:

原文地址:https://www.cnblogs.com/yishuo/p/13892263.html