线程池源代码详解,参数详解

线程池源代码详解,参数详解

ThreadPoolExecutor 构造函数源代码

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);
}

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler);
}

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler);
}

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
    this.ctl = new AtomicInteger(ctlOf(-536870912, 0));
    this.mainLock = new ReentrantLock();
    this.workers = new HashSet();
    this.termination = this.mainLock.newCondition();
    if (corePoolSize >= 0 && maximumPoolSize > 0 && maximumPoolSize >= corePoolSize && keepAliveTime >= 0L) {
        if (workQueue != null && threadFactory != null && handler != null) {
            this.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.workQueue = workQueue;
            this.keepAliveTime = unit.toNanos(keepAliveTime);
            this.threadFactory = threadFactory;
            this.handler = handler;
        } else {
            throw new NullPointerException();
        }
    } else {
        throw new IllegalArgumentException();
    }
}

可以看到,总共只有 7 个参数:
corePoolSize: 线程池最少拥有的线程数,即线程池长时间空闲可必须至少有这么多个线程;

maximumPoolSize: 最大线程数,即线程池最多拥有这么多个线程,当有很多任务需要线程池处理时,也最多只能有这么多个线程被创建来处理这些任务,其他的任务都必须在等待队列里面等待被处理;

keepAliveTime: 空闲线程可以存活的时间。当空闲线程的数量 > corePoolSize 时,多余的空闲线程对多存活 keepAliveTime 就会被销毁;

unit: 时间单位;

workQueue: 工作队列。新任务被提交后,会先进入到此队列中,任务调度时再从队列中取出任务;

threadFactory: 工厂模式创建线程时所使用的工厂;

RejectExecutionHandler handler: 在使用线程池并且使用有界队列的时候,如果队列满了,任务添加到线程池的时候就会有问题,针对这些问题Java线程池提供了以下几种策略:

  • AbortPolicy
    该策略是线程池的默认策略。使用该策略时,如果线程池队列满了就丢掉这个任务,并且抛出RejectExecutionException异常;
 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
   //不做任何处理,直接抛出异常
    throw new RejectedExecutionException("Task " + r.toString() +
                                         " rejected from " +
                                         e.toString());
}
  • DiscardPolicy
    这个策略是和AbortPolicy的Slient版本,如果队列满了,会直接丢掉这个任务并且不会有任何异常。
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
	//就是一个空的方法
}
  • DiscardOldestPolicy
    这个策略从字面意思上也很好理解,丢掉最老的。也就是说如果队列满了,会将最早进入队列的任务删掉腾出空间,再尝试加入队列。
    因为队列是队尾进,队投出,所以队头元素是最老的,因此每次都是移除队头元素再尝试入队。
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
    	//移除队头元素
        e.getQueue().poll();
        //再尝试入队
        e.execute(r);
    }
}
  • CallerRunsPolicy
    使用此策略,如果添加到线程池失败,那么主线程会自己去执行该任务,不会等待线程池中的线程去执行。就像是个急脾气的人,我等不到别人来做这件事就干脆自己干。
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    if (!e.isShutdown()) {
        //直接执行run方法
        r.run();
    }
}
  • 自定义
    如果以上策略都不符合业务场景,那么可以自己定义一个拒绝策略,只要实现RejectedExecutionHandler接口,并且实现rejectedExecution方法就可以了。具体的逻辑就在rejectedExecution方法里面去定义就OK了。
    例如:我定义了我的一个拒绝策略,叫做MyRejectPolicy,里面的逻辑就是打印处理被拒绝的任务内容
public class MyRejectPolicy implements RejectedExecutionHandler{
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        //Sender是我的Runnable类,里面有message字段
        if (r instanceof Sender) {
            Sender sender = (Sender) r;
            //直接打印
            System.out.println(sender.getMessage());
        }
    }
}

这几种策略没有好坏之分,只是使用场景不同,具体哪种合适根据具体场景和业务需要选择,如果需要特殊处理,就自定义就行了。

猜你喜欢

转载自blog.csdn.net/qq_27198345/article/details/108124343
今日推荐