快捷创建线程池方式

Java通过Executors提供四种线程池,分别为:

1、newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需求,可以灵活回收空闲线程,若无可回收则新建线程。

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
//do something
}

2、newFixedThreadPool创建一个定长线程池,可以控制线程最大并发数,超过的线程会在队列中等待。

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
//do something
}
})

3、newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行。

//延迟三秒执行
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
//do something
}
}, 3, TimeUnit.SECONDS); //表示延迟1秒后每隔3秒钟执行一次
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
//do something
}
}, 1, 3, TimeUnit.SECONDS);

4、newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
//do something
}

ThreadPoolExecuto 构造函数的方式创建线程

在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了资源的开销。而线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式,这一方面是由于jdk中Executor框架虽然提供了如newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool()等创建线程池的方法,但都有其局限性,不够灵活;另外由于前面几种方法内部也是通过ThreadPoolExecutor方式实现,使用ThreadPoolExecutor有助于大家明确线程池的运行规则,创建符合自己的业务场景需要的线程池,避免资源耗尽的风险。

        //使用阿里巴巴推荐的创建线程池的方式
//通过ThreadPoolExecutor构造函数自定义参数创建
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,//corePoolSize 线程池的核心线程数量
10,//maximumPoolSize 线程池的最大线程数
100,//keepAliveTime 当线程数大于核心线程数时,多余的空闲线程存活的最长时间
TimeUnit.SECONDS,//时间单位
new ArrayBlockingQueue<>(100),//任务队列,用来储存等待执行任务的队列
new ThreadPoolExecutor.CallerRunsPolicy());//拒绝策略,当提交的任务过多而不能及时处理时,我们可以定制策略来处理任务 for (int i = 0; i < 10; i++) {
executor.execute(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CurrentThread name:" + Thread.currentThread().getName() + "date:" + Instant.now());
});
}
//终止线程池
executor.shutdown();
try {
executor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Finished all threads");

任务队列

1、接提交队列:使用SynchronousQueue实现,SynchronousQueue是一个特殊的BlockingQueue,它没有容量,没执行一个插入操作就会阻塞,需要再执行一个删除操作才会被唤醒,反之每一个删除操作也都要等待对应的插入操作。

2、有界的任务队列:使用ArrayBlockingQueue实现,若有新的任务需要执行时,线程池会创建新的线程,直到创建的线程数量达到corePoolSize时,则会将新的任务加入到等待队列中。若等待队列已满,即超过ArrayBlockingQueue初始化的容量,则继续创建线程,直到线程数量达到maximumPoolSize设置的最大线程数量,若大于maximumPoolSize,则执行拒绝策略。

3、无界的任务队列:使用LinkedBlockingQueue实现,线程池的任务队列可以无限制的添加新的任务,而线程池创建的最大线程数量就是你corePoolSize设置的数量,也就是说在这种情况下maximumPoolSize这个参数是无效的.

4、优先任务队列:通过PriorityBlockingQueue实现。

拒绝策略

1、AbortPolicy策略:抛出 RejectedExecutionException来拒绝新任务的处理。

2、CallerRunsPolicy策略:如果线程池的线程数量达到上限,该策略会把任务队列中的任务放在调用者线程当中运行,如果您的应用程序可以承受此延迟并且你不能任务丢弃任何一个任务请求的话,你可以选择这个策略。

3、DiscardOledestPolicy策略:此策略将丢弃最早的未处理的任务请求。

4、DiscardPolicy策略:不处理新任务,直接丢弃掉。

Java 常用线程池的更多相关文章

  1. java线程池与五种常用线程池策略使用与解析

    背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQu ...

  2. java线程池和五种常用线程池的策略使用与解析

    java线程池和五种常用线程池策略使用与解析 一.线程池 关于为什么要使用线程池久不赘述了,首先看一下java中作为线程池Executor底层实现类的ThredPoolExecutor的构造函数 pu ...

  3. Java中线程池的学习

    线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理.当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程 ...

  4. 沉淀再出发:java中线程池解析

    沉淀再出发:java中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...

  5. Java进阶——— 线程池的原理分析

    前言 在了解线程池之前,其实首先出现的疑问是:为什么要使用线程池,其次是了解什么是线程池,最后是如何使用线程池,带着疑问去学习. 为什么要使用 前面多线程文章中,需要使用线程就开启一个新线程,简单方便 ...

  6. Java 之 线程池

    一.线程池思想概述 如果使用线程的时候就去创建一个线程,这样实现起来非常简便,但是会出现一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低 ...

  7. 深入理解Java之线程池

    原作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本文归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  8. java利用线程池处理集合

    java利用线程池处理集合 2018年07月23日 17:21:19 衍夏成歌 阅读数:866   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/s ...

  9. 深入理解Java之线程池(爱奇艺面试)

    爱奇艺的面试官问 (1) 线程池是如何关闭的 (2) 如何确定线程池的数量 一.线程池销毁,停止线程池 ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown() ...

  10. Java中线程池,你真的会用吗?

    在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Executors静态工厂构建线程池,但一般不建 ...

随机推荐

  1. 3. RabbitMQ 的(Hello World) 和 RabbitMQ 的(Work Queues)工作队列

    3. RabbitMQ 的(Hello World) 和 RabbitMQ 的(Work Queues)工作队列 @ 目录 3. RabbitMQ 的(Hello World) 和 RabbitMQ ...

  2. PHP传递参数(跨文件)的8种常见方法

    以下是 PHP 中跨文件传递参数的 8 种常见方法,按场景和安全性分类整理,附详细说明和示例代码: 一.超全局变量(适合请求间数据共享) 1. $_GET / $_POST 用途:通过 URL 或表单 ...

  3. C 冒泡排序和选择排序

    冒泡排序 理论概念: 从第一个数开始,将相邻的两个数比较,第一个数和第二个数比较,比如说是从小到大的排序,要是后面的数比前面的小则交换两个的位置,这样第一轮比较基数后最大的数就到了最后面,接着进行第二 ...

  4. ThreadLocal 内存泄漏原因和解决方法

    一.ThreadLocal 内存泄漏的原因 ThreadLocal 的内存泄漏问题主要与其底层实现 ThreadLocalMap 的结构和垃圾回收机制有关.以下是核心原因: 1.ThreadLocal ...

  5. 『Plotly实战指南』--样式定制基础篇

    在数据可视化的世界中,一个精心设计的图表不仅能准确传达信息,还能提升整体的专业性和吸引力. 而Plotly作为Python中强大的可视化库,提供了丰富的样式定制功能,帮助我们轻松实现这一目标. 本文从 ...

  6. .net6 Api添加跨域

    参照:(7条消息) .net6使用最小api(8)- 开启跨域模式,通过扩展服务实现_hailang2ll的博客-CSDN博客 步骤: 一.在appsetting.json里添加配置文件 //配置文件 ...

  7. RabbitMQ队列和消息的优先级

    RabbitMQ队列和消息的优先级 如果队列中的消息很多,需要一部分消息被优先消费,这是可以通过为消息和队列设置优先级来实现. 请注意,消息的优先级是相对于队列的优先级而言的.如果队列的最大优先级是1 ...

  8. Java编程--接口(interface)简单用法(一)

    接口是Java中的一个重要的概念. interface:定义了子类要实现的功能.由全局常量和抽象方法组成. 接口的定义 定义一个简单的interface public interface A {  p ...

  9. SSM整合2

    目录 目录结构 数据库 pom.xml依赖 domain dao层 mapper service层 exception包 contorller层 配置文件 applicationContext.xml ...

  10. ChatGPT为何放弃WebSocket?揭秘EventSource的三大决胜优势

    ChatGPT为何放弃WebSocket?揭秘EventSource的三大决胜优势 感觉本篇对你有帮助可以关注一下我的微信公众号(深入浅出谈java),会不定期更新知识和面试资料.技巧!!! Chat ...