Java的线程池都是通过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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}

在Executors工厂类中,Java默认提供了四种类型的线程池。

FixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

这个线程池的特点:

  • 这是一种线程数量固定的线程池,因为corePoolSize和maximunPoolSize都为用户设定的线程数量nThreads;

  • keepAliveTime为0,意味着一旦有多余的空闲线程,就会被立即停止掉,不过因为最多只有nThreads个线程,且corePoolSize和maximunPoolSize值一致,所以这个值无法发挥作用;
  • 阻塞队列采用了LinkedBlockingQueue,它是一个无界队列,由于阻塞队列是一个无界队列,因此永远不可能拒绝任务。

CachedThreadPool

public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

这个线程池的特点

  • 这是一个线程数量可以“无限”扩大(不能超过整型最大值)的线程池;

  • 比较适合处理执行时间比较小的任务;
  • corePoolSize为0,maximumPoolSize为无限大,意味着线程数量可以无限大;
  • keepAliveTime为60S,意味着线程空闲时间超过60S就会被杀死;
  • 采用SynchronousQueue装等待的任务,这个阻塞队列没有存储空间,这意味着只要有请求到来,就必须要找到一条工作线程处理他,如果当前没有空闲的线程,那么就会再创建一条新的线程。

SingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}

这个线程池的特点:

  • 只有一个线程,使用了无界队列LinkedBlockingQueue,某种意义上等同于newFixedThreadPool(1);

  • 因为只有一个线程,所以能够保证所有任务是FIFO地执行。

ScheduledThreadPool

public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}

ScheduledThreadPoolExecutor继承自ThreadPoolExecutor。

这个线程池的特点:

它接收SchduledFutureTask类型的任务,有两种提交任务的方式:

  • scheduledAtFixedRate

  • scheduledWithFixedDelay

从提交方式可以看出,这个线程池主要处理定时任务或延时任务。

SchduledFutureTask接收的参数:

  • time:任务开始的时间s

  • equenceNumber:任务的序号
  • period:任务执行的时间间隔

它采用DelayQueue存储等待的任务:

  • DelayQueue内部封装了一个PriorityQueue,它会根据time的先后时间排序,若time相同则根据sequenceNumber排序;

  • DelayQueue也是一个无界队列;

工作线程的执行过程:

  • 工作线程会从DelayQueue取已经到期的任务去执行;

  • 执行结束后重新设置任务的到期时间,再次放回DelayQueue

#########

Java默认提供的线程池的更多相关文章

  1. Java并发编程之线程池及示例

    1.Executor 线程池顶级接口.定义方法,void execute(Runnable).方法是用于处理任务的一个服务方法.调用者提供Runnable 接口的实现,线程池通过线程执行这个 Runn ...

  2. JAVA基础拾遗-论线程池的线程粒度划分与深浅放置

    摘要:多线程任务处理对提高性能很有帮助,在Java中提供的线程池也方便了对多线程任务的实现.使用它很简单,而如果进行了不正确的使用,那么代码将陷入一团乱麻.因此如何正确地使用它,如以下分享,这个技能你 ...

  3. Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  4. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  5. Java多线程-新特性-线程池

    Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...

  6. Java并发编程:线程池的使用(转)

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  7. java 线程之executors线程池

    一.线程池的作用 平时的业务中,如果要使用多线程,那么我们会在业务开始前创建线程,业务结束后,销毁线程.但是对于业务来说,线程的创建和销毁是与业务本身无关的,只关心线程所执行的任务.因此希望把尽可能多 ...

  8. 深入理解Java自带的线程池和缓冲队列

    前言 线程池是什么 线程池的概念是初始化线程池时在池中创建空闲的线程,一但有工作任务,可直接使用线程池中的线程进行执行工作任务,任务执行完成后又返回线程池中成为空闲线程.使用线程池可以减少线程的创建和 ...

  9. Java并发编程:线程池的使用(转载)

    转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

随机推荐

  1. 深入浅出地,彻彻底底地理解python中的编码

    python处理文本的功能非常强大,但是如果是初学者,没有搞清楚python中的编码机制,也经常会遇到乱码或者decode error.本文的目的是简明扼要地说明python的编码机制,并给出一些建议 ...

  2. django迁移:全局、局部

    django迁移:全局.局部 django 数据库迁移(migrate)应该知道的一些事 https://blog.csdn.net/stonesola/article/details/6975861 ...

  3. java 多线程 day09 线程池

    import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.c ...

  4. 如何确定LDA的主题个数

    本文参考自:https://www.zhihu.com/question/32286630 LDA中topic个数的确定是一个困难的问题. 当各个topic之间的相似度的最小的时候,就可以算是找到了合 ...

  5. PEP8编码规范

    1.代码布局设计 1.1 缩进 -4个空格进行缩进 1.2 tab键-在python2中tab和空格是混用的,但是在python中基本上使用tab(pycharm开发工具会自动对代码缩进) 1.3 最 ...

  6. Java设计原则—开闭原则(转)

    原文出自:http://www.cnblogs.com/muzongyan/archive/2010/08/05/1793454.html 开闭原则(Open Closed Principle)是Ja ...

  7. 【转】网页窗口DIV自定义拖动

    一个来自网上的东西- -被我捡到了 然后我访问到了 发出来就可以粘贴复制自己做成js文件了吧 // by zhangxinxu welcome to visit my personal website ...

  8. [2012-12-18 14:59:31]AS3 常用正则表达式的总结-不用google了,我帮收集的很多了

    正则表达式是一种通用的标准,大部分计算机语言都支持正则表达式,包括as3,这里转摘出了一些常用的正则表达式语句,大家用到的时候就不用自己写了.红色字体为常用正则:下面这个类是我自己写的一个示例,想必大 ...

  9. getAttribute() 与 attr() 的区别

    getAttribute() 和 attr() 都是获取元素属性的方法,只是一种是 JS 写法,一种是 JQ 写法,但其实它们是有区别的. 主要区别 调用 getAttribute() 的主体必须是元 ...

  10. C++之图片旋转90,再保存

    下面测试代码只需要全部放在一个.cpp文件里就行 //#include "stdafx.h"#include <stdio.h>#include <string& ...