用ThreadPoolExecutor手动创建线程池

用ThreadPoolExecutor手动创建线程池

首先我们看一下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;
}

我们这里就通过这构造方法的七个参数来创建一个ThreadPoolExecutor对象

ExecutorService threadPool = new ThreadPoolExecutor(
    2,
    5,
    3,
    TimeUnit.SECONDS,
    new LinkedBlockingDeque<>(3),
    Executors.defaultThreadFactory(),
    new ThreadPoolExecutor.AbortPolicy());

我们这里创建的线程默认开启2个线程,最大可开启5个线程,当线程开启后3秒没被使用就会关闭该线程,允许3个用户进入LinkedBlockingDeque阻塞队列等待,用了Executors对象提供的默认线程创建工厂,AbortPolicy表示拒绝任务的处理程序。

线程工厂

我们这里来看一下Executors默认的线程创建工厂,这里用了静态内部类实现了ThreadFactory接口

static class DefaultThreadFactory implements ThreadFactory {
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    DefaultThreadFactory() {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
        Thread.currentThread().getThreadGroup();
        namePrefix = "pool-" +
            poolNumber.getAndIncrement() +
            "-thread-";
    }

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r,
                              namePrefix + threadNumber.getAndIncrement(),
                              0);
        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}

我们这里可以看到Executors的DefaultThreadFactory提供了一个无参的构造方法,当我们不想自己实现ThreadFactory接口的时候可以直接调用Executors的DefaultThreadFactory类,当然我们可以看到其实ThreadFactory也有许多的实现类,我们这里就不一一赘述了,有兴趣的小伙伴也可以自己写ThreadFactory接口的实现类

拒绝策略

在这里插入图片描述

我们可以看到RejectedExecutionHandler接口的四个实现类,都在ThreadPoolExecutor中

我们这里分别来看下

AbortPolicy
public static class AbortPolicy implements RejectedExecutionHandler {
    /**
         * Creates an {@code AbortPolicy}.
         */
    public AbortPolicy() { }

    /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }
}

超出最大承载会抛出RejectedExecutionException异常

最大承载: Deque + max

CallerRunsPolicy
public static class CallerRunsPolicy implements RejectedExecutionHandler {
    /**
     * Creates a {@code CallerRunsPolicy}.
     */
    public CallerRunsPolicy() { }

    /**
     * Executes task r in the caller's thread, unless the executor
     * has been shut down, in which case the task is discarded.
     *
     * @param r the runnable task requested to be executed
     * @param e the executor attempting to execute this task
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}

如果超载了,被什么线程调用的就会回到该线程取执行方法

DiscardOldestPolicy
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
    public DiscardOldestPolicy() { }

    /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll();
            e.execute(r);
        }
    }
}

队列满了,尝试和最早的竞争,也不会抛出异常

DiscardPolicy
public static class DiscardPolicy implements RejectedExecutionHandler {
    /**
     * Creates a {@code DiscardPolicy}.
     */
    public DiscardPolicy() { }

    /**
     * Does nothing, which has the effect of discarding task r.
     *
     * @param r the runnable task requested to be executed
     * @param e the executor attempting to execute this task
     */
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    }
}

队列满了,丢掉任务,不会抛出异常

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
通过ThreadPoolExecutor创建线程池的方式有多种。其中一种方式是使用ThreadPoolExecutor的构造函数来手动创建线程池。可以设置线程池的核心线程池大小、最大线程池大小、线程空闲时间、任务队列、线程工厂和拒绝策略等参数。例如,可以使用以下代码创建一个线程池ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 2, // 核心线程池大小 5, // 最大线程池大小 3, // 线程空闲时间 TimeUnit.SECONDS, // 时间单位 new LinkedBlockingQueue<>(3), // 任务队列 Executors.defaultThreadFactory(), // 线程工厂 new ThreadPoolExecutor.AbortPolicy() // 拒绝策略 ); 在这个例子中,线程池的核心线程池大小为2,最大线程池大小为5,线程空闲时间为3秒,任务队列使用LinkedBlockingQueue,线程工厂使用默认的线程工厂,拒绝策略使用AbortPolicy。然后可以通过execute方法向线程池提交任务。最后,记得在不需要使用线程池时调用shutdown方法关闭线程池。 #### 引用[.reference_title] - *1* *2* [ThreadPoolExecutor 手动创建线程池](https://blog.csdn.net/Q17532573105/article/details/124698108)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [通过ThreadPoolExecutor的方式创建线程池](https://blog.csdn.net/m0_45303174/article/details/123587122)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值