JAVA线程池使用

479 阅读2分钟

线程池的创建

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("xxx-thread-%d").build();

ExecutorService executor = new ThreadPoolExecutor(16, 
                                                  32, 
                                                  60000L, 
                                                  TimeUnit.SECONDS, 
                                                  new LinkedBlockingQueue<Runnable>(200), 
                                                  namedThreadFactory, 
                                                  new DiscardOldestPolicy());

ThreadPoolExecutor构造函数说明

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) {
            throw new IllegalArgumentException();
        }
        if (workQueue == null || threadFactory == null || handler == null){
            throw new NullPointerException();
        }
        this.acc = System.getSecurityManager() == null ? null : AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

corePoolSize

保持在池中的线程数,即使它们是空闲的; 设置{@code allowCoreThreadTimeOut},允许线程数低于corePoolSize时,线程也因为空闲而终止。

maximumPoolSize

池中允许的最大线程数

keepAliveTime

当线程数大于corePoolSize时,多余的空闲线程等待新任务的最大时间,超过此时间会被回收。

unit

keepAliveTime的时间单位

workQueue

用于在任务执行前保存任务的队列。这个队列将只包含{@code execute}方法提交的{@code Runnable}任务。

threadFactory

执行程序创建新线程时使用的线程工厂

handler

RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。

四种默认的饱和策略

AbortPolicy

默认的饱和策略,直接抛出java.util.concurrent.RejectedExecutionException异常

CallerRunsPolicy

任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务。这个策略的缺陷就是可能会阻塞主线程。

DiscardPolicy

让被线程池拒绝的任务直接抛弃,不会抛异常也不会执行。

DiscardOldestPolicy

当任务被拒绝添加时,会抛弃任务队列中最先加入队列的,再把这个新任务添加进去。

自定义饱和策略

  • 实现java.util.concurrent.RejectedExecutionHandler接口
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author 
 * @version 1.0.0
 * @Description  舍弃队列中最先加入的五条任务,并将新的任务加入队尾
 * @date 2020/6/2 21:25
 * @since 1.8
 */
public class MyRejectedPolicy implements RejectedExecutionHandler {

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        if (!executor.isShutdown()){
            executor.getQueue().poll();
            executor.getQueue().poll();
            executor.getQueue().poll();
            executor.getQueue().poll();
            executor.getQueue().poll();
            executor.getQueue().offer(r);
        }
    }
}