线程池原理之七大参数和四种拒绝策略

一、说说线程池的底层工作原理

线程池原理之七大参数和四种拒绝策略_第1张图片

  •  线程池主要处理流程解释(重要)

1、在创建了线程池后,等待提交过来的任务请求。

2、当调用execute()方法添加一个任务请求,线程池会做如下判断:

       2.1 如果正在运行的线程数小于或者等于corePoolSize,那么马上会创建线程运行这个任务;

       2.2 如果正在运行的线程数大于corePoolSize,那么会将这个任务放入队列;

       2.3 如果这时候队列满了并且正在运行的线程数量还小于maximumPoolSize,那么还是要创建非核心线程运行这个任务;

       2.4 如果队列满了并且线程数大于或者等于maximumPoolSize,那么会启动饱和拒绝策略来执行。

3、当一个线程完成时,它会从队列中取下一个任务来执行。

4、当一个线程无事可做,且超过一定的时间(keepAliveTime)时,线程池会判断:

       如果当前运行的线程数大于corePoolSize,那么这个线程会停掉。

       所以线程池的所有任务完成后,它最终会收缩到corePoolSize的大小。


二、线程池七大参数

  • (1)corePoolSize:线程池中常驻核心线程数
  • (2)maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1
  • (3)keepAliveTime:多余的空闲线程存活时间。当前线程池数量超过corePoolSize时,当空闲时间到达keepAliveTime值时,多余空闲线程会被销毁直到只剩下corePoolSize个线程为止。
  • (4)unit:keepAliveTime的时间单位
  • (5)workQueue:任务队列,被提交但尚未执行的任务
  • (6)threadFactory:表示生成线程池中的工作线程的线程工厂,用于创建线程,一般为默认线程工厂即可
  • (7)handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何来拒绝来请求的Runnable的策略

底层代码: 

第一步:
ExecutorService threadPool = Executors.newFixedThreadPool(5);
 
第二步:
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue());
    }
 
第三步:
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
 
第四步:
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue 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;
    }

三、线程池四种拒绝策略

 (1)AbortPolicy(默认)
       直接抛出RejectedExecutionException异常阻止系统正常运行。
 (2)CallerRunsPolicy
       “调用者运行”一种调节机制,该策略既不会丢弃任务,也不会抛出异常,而是将某些任务回退给调用者,从而降低新任务的流量。
 (3)DiscardOldestPolicy
       抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。   
 (4)DiscardPolicy
       直接丢弃任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种方案。

底层:以上内置策略均实现了RejectExecutionHandler接口

何时使用:  等待队列已经排满了,再也塞不下新任务,同时线程池中线程也已经达到maximumPoolSize数量,无法继续为新任务服务,这个时候就需要使用拒绝策略来处理。

四、线程池四种拒绝策略场景Demo:

(1)AbortPolicy场景演示

public class ThreadPoolDemoFour {
    public static void main(String[] args) {
        // 自定义线程池
        ExecutorService threadPool = new ThreadPoolExecutor(3,
                5,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
 
        try {
            for (int i = 0; i < 10; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "\t 办理业务");
                });
 
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }
}


程序执行结果如下:直接抛出RejectedExecutionException异常阻止系统正常运行
(2)CallerRunsPolicy场景演示
 

public class ThreadPoolDemoFour {
    public static void main(String[] args) {
        // 自定义线程池
        ExecutorService threadPool = new ThreadPoolExecutor(3,
                5,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());
 
        try {
            for (int i = 0; i < 10; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "\t 办理业务");
                });
 
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }
}


程序执行结果如下:如果队列已满,且执行线程数大于等于maximumPoolSize时,会将某些任务退回给调用者。
(3)DiscardOldestPolicy场景演示
 

public class ThreadPoolDemoFour {
    public static void main(String[] args) {
        // 自定义线程池
        ExecutorService threadPool = new ThreadPoolExecutor(3,
                5,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy());
 
        try {
            for (int i = 0; i < 10; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "\t 办理业务");
                });
 
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }
}


程序执行结果如下:抛弃队列中等待最久的任务
(4)DiscardPolicy场景演示
 

public class ThreadPoolDemoFour {
    public static void main(String[] args) {
        // 自定义线程池
        ExecutorService threadPool = new ThreadPoolExecutor(3,
                5,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(1),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardPolicy());
 
        try {
            for (int i = 0; i < 10; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "\t 办理业务");
                });
 
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
    }
}


程序执行结果如下:直接丢弃任务,不予任何处理,也不抛出异常。

 

你可能感兴趣的:(java)