线程池实现原理

向线程池提交任务后,线程池如何来处理这个任务,之前我们了解了7个参数,我们通过这些参数来串联其线程池的实现原理。

1、在创建了线程池后,开始等待请求

2、当调用execute()方法添加请求任务时:

  • 如果正在运行的线程小于corePoolSize(核心线程数),那么马上创建线程执行任务;
  • 如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入阻塞队列中;
  • 如果这个时候队列满了且正在运行的线程数量还小于maximumPoolSize(最大线程数),那么再创建非核心线程来执行任务
  • 如果这个时候队列满了且正在运行的线程数量还大于或等于maximumPoolSize(最大线程数),那么线程池会启动饱和拒绝策略来执行

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

4、当一个线程无事可做并超过了一定的时间(KeepAliveTime)时,线程会回收。

拒绝策略

等待队列已经排满,再也塞不下新任务,同时线程池中的max线程也到达上限了,无法继续执行新任务服务,这时候就需要据拒绝策略。

内置的拒绝策略有四种:

  1. AbortPolicy(默认的拒绝策略):直接抛出RejectedExecutionException异常
  2. CallerRunPolicy:回退任务,该策略不抛弃任务,也不抛出异常,而是将任务会退给调用者,从而降低新任务的流量
  3. DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务加人队列中尝试再次提交当前任务。
  4. DiscardPolicy:该策略默默地丢弃无法处理的任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种策略。

根据阿里巴巴手册,定义线程池需要使用ThreadPoolExecutor来创建:

package com.JucPool;

import java.util.concurrent.*;

public class demo1 {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
//根据自己的处理器数量+1
Runtime.getRuntime().availableProcessors()+1,
2L,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
try{
for (int i = 0; i < 8; i++) {
executor.execute(()->{
System.out.println(Thread.currentThread().getName()+"\t任务执行");
});
}
} finally {
executor.shutdown();
}
}
}

如果项目时CPU密集型,则设置的线程池的最大线程数是:CPU数+1~2个。

JUC之线程池的实现原理以及拒绝策略的更多相关文章

  1. 线程池ThreadPoolExecutor里面4种拒绝策略

    ThreadPoolExecutor类实现了ExecutorService接口和Executor接口,可以设置线程池corePoolSize,最大线程池大小,AliveTime,拒绝策略等.常用构造方 ...

  2. Java8线程池ThreadPoolExecutor底层原理及其源码解析

    小侃一下 日常开发中, 或许不会直接new线程或线程池, 但这些线程相关的基础或思想是非常重要的, 参考林迪效应; 就算没有直接用到, 可能间接也用到了类似的思想或原理, 例如tomcat, jett ...

  3. 基于C++11实现线程池的工作原理

    目录 基于C++11实现线程池的工作原理. 简介 线程池的组成 1.线程池管理器 2.工作线程 3.任务接口, 4.任务队列 线程池工作的四种情况. 1.主程序当前没有任务要执行,线程池中的任务队列为 ...

  4. 深入源码分析Java线程池的实现原理

    程序的运行,其本质上,是对系统资源(CPU.内存.磁盘.网络等等)的使用.如何高效的使用这些资源是我们编程优化演进的一个方向.今天说的线程池就是一种对CPU利用的优化手段. 通过学习线程池原理,明白所 ...

  5. 21.线程池ThreadPoolExecutor实现原理

    1. 为什么要使用线程池 在实际使用中,线程是很占用系统资源的,如果对线程管理不善很容易导致系统问题.因此,在大多数并发框架中都会使用线程池来管理线程,使用线程池管理线程主要有如下好处: 降低资源消耗 ...

  6. 线程池续:你必须要知道的线程池submit()实现原理之FutureTask!

    前言 上一篇内容写了Java中线程池的实现原理及源码分析,说好的是实实在在的大满足,想通过一篇文章让大家对线程池有个透彻的了解,但是文章写完总觉得还缺点什么? 上篇文章只提到线程提交的execute( ...

  7. 深入源码,深度解析Java 线程池的实现原理

    java 系统的运行归根到底是程序的运行,程序的运行归根到底是代码的执行,代码的执行归根到底是虚拟机的执行,虚拟机的执行其实就是操作系统的线程在执行,并且会占用一定的系统资源,如CPU.内存.磁盘.网 ...

  8. 细说JUC的线程池架构

    前言 线程的创建是需要JVM和OS(操作系统)相互配合的,一次的创建要花费许多的资源. 1.首先,JVM要为该线程分配堆栈和初始化大量内存块,栈内存至少是1MB. 2.其次便是要进行系统的调用,在OS ...

  9. JUC自定义线程池练习

    JUC自定义线程池练习 首先上面该线程池的大致流程 自定义阻塞队列 首先定义一个双向的队列和锁一定两个等待的condition 本类用lock来控制多线程下的流程执行 take和push方法就是死等, ...

随机推荐

  1. 第二周Python笔记之 变量的三元运算

    如果变量a小于b,则d的值取a变量的值,否则取c变量的值

  2. redis查看redis 客户端状态

    查看redis客户端连接 redis-cli info clients # Clients connected_clients:6000 client_longest_output_list:0 cl ...

  3. svn服务器用户名密码更改后,如何更新本地用户名密码

    在提交时,IDE会给出这样的提示,说明用户名密码已更改 在命令行输入 svn ls https:XXX(项目的地址),具体步骤如下图

  4. IDEA微服务项目SpringBoot一键(批量)顺序启动

    找到 搜索 RunDashboard <option name="configurationTypes"> <set> <option value=& ...

  5. C语言之可变长参数格式化

    概述 本文演示环境: win10 + Vs2015 可变长参数格式化 两个概念: 1. 参数长度不定, 2. 参数格式化. 使用函数 vsnprintf 结合 va_list. 源码 写好了函数, 照 ...

  6. ubuntu 16.04 server安装Bittorrent Transmission

    访问web服务 使用http://192.168.1.8:9091 这样的方式管理下载. http://192.168.1.8:9091/transmission/web/ 操作服务 sudo ser ...

  7. c++内存分布之虚函数(单一继承)

    系列 c++内存分布之虚函数(单一继承) [本文] c++内存分布之虚函数(多继承) 结论 1.虚函数表指针 和 虚函数表 1.1 影响虚函数表指针个数的因素只和派生类的父类个数有关.多一个父类,派生 ...

  8. Lucky Substrings

    而在26以内且属于fibonacci数列的数为1,2,3,5,8,13,21时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 A string s is LUCKY if ...

  9. [源码解析] PyTorch 分布式之弹性训练(4)---Rendezvous 架构和逻辑

    [源码解析] PyTorch 分布式之弹性训练(4)---Rendezvous 架构和逻辑 目录 [源码解析] PyTorch 分布式之弹性训练(4)---Rendezvous 架构和逻辑 0x00 ...

  10. ORW-测信道攻击

    做SCTF时碰到一个没看过的题型,比赛结束之后才知道是orw的一个玩法,测信道攻击.主要特点就是只给使用open,read,但是不给write,即无法把flag输出到终端.这里可以通过把flag读到栈 ...