文档章节

Java四种线程池两篇文章节选总结

亭子happy
 亭子happy
发布于 01/18 15:18
字数 1672
阅读 19
收藏 0

Executor 可 以 创 建 3 种 类 型 的 ThreadPoolExecutor 线 程 池:

 1. FixedThreadPool

创建固定长度的线程池,每次提交任务创建一个线程,直到达到线程池的最大数量,线程池的大小不再变化。

这个线程池可以创建固定线程数的线程池。特点就是可以重用固定数量线程的线程池。它的构造源码如下:

1

2

3

4

5

public static ExecutorService newFixedThreadPool(int nThreads) { 

        return new ThreadPoolExecutor(nThreads, nThreads, 0L,

                                      TimeUnit.MILLISECONDS, 

                                      new LinkedBlockingQueue<Runnable>()); 

  • FixedThreadPool的corePoolSize和maxiumPoolSize都被设置为创建FixedThreadPool时指定的参数nThreads。
  • 0L则表示当线程池中的线程数量操作核心线程的数量时,多余的线程将被立即停止
  • 最后一个参数表示FixedThreadPool使用了无界队列LinkedBlockingQueue作为线程池的做工队列,由于是无界的,当线程池的线程数达到corePoolSize后,新任务将在无界队列中等待,因此线程池的线程数量不会超过corePoolSize,同时maxiumPoolSize也就变成了一个无效的参数,并且运行中的线程池并不会拒绝任务。

FixedThreadPool运行图如下

执行过程如下:

1.如果当前工作中的线程数量少于corePool的数量,就创建新的线程来执行任务。

2.当线程池的工作中的线程数量达到了corePool,则将任务加入LinkedBlockingQueue。

3.线程执行完1中的任务后会从队列中去任务。

注意LinkedBlockingQueue是无界队列,所以可以一直添加新任务到线程池。

 

2. SingleThreadExecutor  

SingleThreadExecutor是使用单个worker线程的Executor。特点是使用单个工作线程执行任务。它的构造源码如下:

1

2

3

4

5

6

public static ExecutorService newSingleThreadExecutor() {

        return new FinalizableDelegatedExecutorService

            (new ThreadPoolExecutor(11,

                                    0L, TimeUnit.MILLISECONDS,

                                    new LinkedBlockingQueue<Runnable>()));

}

  

SingleThreadExecutor的corePoolSize和maxiumPoolSize都被设置1。

其他参数均与FixedThreadPool相同,其运行图如下:

 

执行过程如下:

1.如果当前工作中的线程数量少于corePool的数量,就创建一个新的线程来执行任务。

2.当线程池的工作中的线程数量达到了corePool,则将任务加入LinkedBlockingQueue。

3.线程执行完1中的任务后会从队列中去任务。

注意:由于在线程池中只有一个工作线程,所以任务可以按照添加顺序执行。

 

 3. CachedThreadPool

 CachedThreadPool是一个”无限“容量的线程池,它会根据需要创建新线程。特点是可以根据需要来创建新的线程执行任务,没有特定的corePool。下面是它的构造方法:

1

2

3

4

5

public static ExecutorService newCachedThreadPool() {

        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

                                      60L, TimeUnit.SECONDS,

                                      new SynchronousQueue<Runnable>());

}

  

CachedThreadPool的corePoolSize被设置为0,即corePool为空;maximumPoolSize被设置为Integer.MAX_VALUE,即maximum是无界的。这里keepAliveTime设置为60秒,意味着空闲的线程最多可以等待任务60秒,否则将被回收。

 

CachedThreadPool使用没有容量的SynchronousQueue作为主线程池的工作队列,它是一个没有容量的阻塞队列。每个插入操作必须等待另一个线程的对应移除操作。这意味着,如果主线程提交任务的速度高于线程池中处理任务的速度时,CachedThreadPool会不断创建新线程。极端情况下,CachedThreadPool会因为创建过多线程而耗尽CPU资源。其运行图如下:

 

执行过程如下:

1.首先执行SynchronousQueue.offer(Runnable task)。如果在当前的线程池中有空闲的线程正在执行SynchronousQueue.poll(),那么主线程执行的offer操作与空闲线程执行的poll操作配对成功,主线程把任务交给空闲线程执行。,execute()方法执行成功,否则执行步骤2

2.当线程池为空(初始maximumPool为空)或没有空闲线程时,配对失败,将没有线程执行SynchronousQueue.poll操作。这种情况下,线程池会创建一个新的线程执行任务。

3.在创建完新的线程以后,将会执行poll操作。当步骤2的线程执行完成后,将等待60秒,如果此时主线程提交了一个新任务,那么这个空闲线程将执行新任务,否则被回收。因此长时间不提交任务的CachedThreadPool不会占用系统资源。

SynchronousQueue是一个不存储元素阻塞队列,每次要进行offer操作时必须等待poll操作,否则不能继续添加元素。

 

最后 来个各种阻塞队列的说明和比较:

  Java并发包中的阻塞队列一共7个,当然他们都是线程安全的。 

  ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。 

  LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。 

  PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。 

  DealyQueue:一个使用优先级队列实现的无界阻塞队列。 

  SynchronousQueue:一个不存储元素的阻塞队列。 

  LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。 

  LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

 

调度线程池ScheduledThreadPool使用示例

package com.expgiga.JUC;


import java.util.Random;
import java.util.concurrent.*;

/**
 * 一、线程池:提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外的开销,提高了响应速度。
 * 二、线程池的体系结构:
 *    java.util.concurrent.Executor:负责线程的使用与调度的根接口
 *       |-- ExecutorService 子接口:线程池的主要接口
 *          |-- ThreadPoolExecutor 线程池的实现类
 *          |-- ScheduledExecutorService 子接口:负责线程的调度
 *             |--ScheduledThreadPoolExecutor:继承了ThreadPoolExecutor实现了ScheduledExecutorService
 * <p>
 * 三、工具类:Executors
 * ExecutorService newFixedThreadPool():创新固定大小的线程池、
 * ExecutorService newCacheThreadPool():缓存线程池,线程池的数量不固定,可以根据需求自动的而更改数量。
 * ExecutorService newSingleThreadExecutor():创建单个线程池,线程池中只有一个线程
 * <p>
 * ScheduledExecutorService newScheduledThreadPool():创建固定大小的线程,可以延迟或定时执行任务。
 */
public class TestScheduledThreadPool {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);

        for (int i = 0; i < 5; i++) {
            Future<Integer> result = pool.schedule(new Callable<Integer>() {

                @Override
                public Integer call() throws Exception {
                    int num = new Random().nextInt(100);//生成随机数
                    System.out.println(Thread.currentThread().getName() + " : " + num);
                    return num;
                }
            }, 3, TimeUnit.SECONDS);


            System.out.println(result.get());
        }

        pool.shutdown();
    }
}
--------------------- 
作者:u013063153 
来源:CSDN 
原文:https://blog.csdn.net/u013063153/article/details/76407258 
版权声明:本文为博主原创文章,转载请附上博文链接!

本文转载自:http://www.cnblogs.com/baizhanshi/p/5469948.html

共有 人打赏支持
亭子happy
粉丝 118
博文 215
码字总数 46492
作品 0
海淀
程序员
私信 提问
线程池中使用ThreadLocal方案

人工手打,翻译自:https://moelholm.com/2017/07/24/spring-4-3-using-a-taskdecorator-to-copy-mdc-data-to-async-threads本来想自己写一篇关于线程池threadlocal的,偶然看到这篇文章觉得...

whaon
2018/12/07
0
0
JAVA多线程和并发基础面试问答

多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题。(校对注:...

LCZ777
2014/05/26
0
0
Java中线程池,你真的会用吗?

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

HollisChuang's Blog
2018/10/27
0
0
如何在面试时搞定 Java 虚拟机?

作者 | 倪升武 责编 | 胡巍巍 笔者最近抽空看了一点《深入理解Java虚拟机》,本篇文章主要来总结一下Java虚拟机内存的各个区域,以及这些区域的作用、服务对象以及其中可能产生的问题,作为大...

CSDN资讯
2018/12/05
0
0
JAVA多线程和并发基础面试问答

Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一...

hanzhankang
2014/01/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

RocketMQ高性能之底层存储设计

说在前面 RocketMQ在底层存储上借鉴了Kafka,但是也有它独到的设计,本文主要关注深刻影响着RocketMQ性能的底层文件存储结构,中间会穿插一点点Kafka的东西以作为对比。 例子 Commit Log,一...

薛定谔的旺
21分钟前
2
0
实战:基于Spring Boot快速开发RESTful风格API接口

写在前面的话 这篇文章计划是在过年期间完成的,示例代码都写好了,结果亲戚来我家做客,文章没来得及写。已经很久没有更新文章了,小伙伴们,有没有想我啊。言归正传,下面开始,今天的话题...

JAVA_冯文议
29分钟前
1
0
Anaconda3 5.0.0中配置Python 3.6 + TensorFlow环境

参考:https://blog.csdn.net/hu_zhenghui/article/details/78156193

Pasenger
33分钟前
0
0
Nginx反向代理Tomcat配置

Nginx代理Tomcat 为什么要为Tomcat配置反向代理? 1)如果同一台机器既有nginx又有Tomcat,则会产生端口冲突2)我们需要把8080端口变成80端口3)nginx对于静态的请求速度上要优于Tomcat,T...

wzb88
46分钟前
10
0
JavaScript email邮箱/邮件地址的正则表达式及分析

在做用户注册时,常会用到邮箱/邮件地址的正则表达式。本文列举了几种方案,大家可以根据自己的项目情况,选择最适合的方案。 方案1 (常用) 规则定义如下: 以大写字母[A-Z]、小写字母[a-z]...

前端小攻略
48分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部