线程池拒绝策略实战手写线程池

188 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

等待队列也已经排满了,再也塞不下新任务了同时,线程池中的max线程也达到了,无法继续为新任务服务。 这时候我们就需要拒绝策略机制合理的处理这个问题。

jdk内置的拒绝策略 直接抛出异常 回退到调用时 抛弃等待最久的任务,再尝试提交 直接丢弃,不做任何处理

AbortPolicy(默认):直接抛出RejectedExecutionException异常阻止系统正常运行。

CallerRunsPolicy: "调用者运行"一种调节机制,该策略既不会拋弃任务,也不会抛出异常,而是将某些任务回退到调用DiscardOldestolicy:抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。

Discardolicy:直接丟弃任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一-种方案。

而是将某些任务回退到调用者,从而降低新任务的流量。

线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。, 说明:使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决 资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或 者“过度切换"的问题。

线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明: Executors 返回的线程池对象的弊端如下:

  1. FixedThreadPool和SingleThreadPool: 允许的请求队列长度为Integer .MAX_ _VALUE,可 能会堆积大量的请求,从而导致00M。
  2. CachedThreadPool 和ScheduledThreadPool: 允许的创建线程数量为Integer .MAX_ _VALUE,可能会创建大量的线程,从而导致00M。

不能用系统jdk的,需要自己手写线程池

自定义线程池使用:

手写线程池

    package com.wsx.threadPool;


import java.util.concurrent.*;

    public class ThreadPoolDemo {
        public static void main(String[] args) {
            //System.out.println(Runtime.getRuntime().availableProcessors());
            ExecutorService threadPool = new ThreadPoolExecutor(
                    2,
                    5,
                    2L, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>(3),
                    Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.AbortPolicy());

            try {
                for (int i = 1; i <= 8 ; i++) {
                    threadPool.execute(()->{
                        System.out.println(Thread.currentThread().getName()+"线程运行");
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                threadPool.shutdown();
            }

        }
    }