Executors 可以创建以下六种线程池:

  • FixedThreadPool(n):创建一个数量固定的线程池,超出的任务会在队列中等待空闲的线程,可用于控制程序的最大并发数。
  • CachedThreadPool():短时间内处理大量工作的线程池,会根据任务数量产生对应的线程,并试图缓存线程以便重复使用,如果限制 60 秒没被使用,则会被移除缓存。
  • SingleThreadExecutor():创建一个单线程线程池。
  • ScheduledThreadPool(n):创建一个数量固定的线程池,支持执行定时性或周期性任务。
  • SingleThreadScheduledExecutor():此线程池就是单线程的 newScheduledThreadPool。
  • WorkStealingPool(n):Java 8 新增创建线程池的方法,创建时如果不设置任何参数,则以当前机器处理器个数作为线程个数,此线程池会并行处理任务,不能保证执行顺序。

1.FixedThreadPool 使用

创建固定个数的线程池,具体示例如下:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
for (int i = 0; i < 3; i++) {fixedThreadPool.execute(() -> {System.out.println("CurrentTime - " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});
}

以上程序执行结果如下:

CurrentTime - 2019-06-27 20:58:58CurrentTime - 2019-06-27 20:58:58CurrentTime - 2019-06-27 20:58:59

根据执行结果可以看出,newFixedThreadPool(2) 确实是创建了两个线程,在执行了一轮(2 次)之后,停了一秒,有了空闲线程,才执行第三次。

2.CachedThreadPool 使用

根据实际需要自动创建带缓存功能的线程池,具体代码如下:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {cachedThreadPool.execute(() -> {System.out.println("CurrentTime - " +LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});
}

以上程序执行结果如下:

CurrentTime - 2019-06-27 21:24:46CurrentTime - 2019-06-27 21:24:46CurrentTime - 2019-06-27 21:24:46CurrentTime - 2019-06-27 21:24:46CurrentTime - 2019-06-27 21:24:46CurrentTime - 2019-06-27 21:24:46CurrentTime - 2019-06-27 21:24:46CurrentTime - 2019-06-27 21:24:46CurrentTime - 2019-06-27 21:24:46CurrentTime - 2019-06-27 21:24:46

根据执行结果可以看出,newCachedThreadPool 在短时间内会创建多个线程来处理对应的任务,并试图把它们进行缓存以便重复使用。

3.SingleThreadExecutor 使用

创建单个线程的线程池,具体代码如下:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 3; i++) {singleThreadExecutor.execute(() -> {System.out.println("CurrentTime - " +LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});
}

以上程序执行结果如下:

CurrentTime - 2019-06-27 21:43:34CurrentTime - 2019-06-27 21:43:35CurrentTime - 2019-06-27 21:43:36

4.ScheduledThreadPool 使用

创建一个可以执行周期性任务的线程池,具体代码如下:

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);
scheduledThreadPool.schedule(() -> {System.out.println("ThreadPool:" + LocalDateTime.now());
}, 1L, TimeUnit.SECONDS);
System.out.println("CurrentTime:" + LocalDateTime.now());

以上程序执行结果如下:

CurrentTime:2019-06-27T21:54:21.881ThreadPool:2019-06-27T21:54:22.845

根据执行结果可以看出,我们设置的 1 秒后执行的任务生效了。

5.SingleThreadScheduledExecutor 使用

创建一个可以执行周期性任务的单线程池,具体代码如下:

ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
singleThreadScheduledExecutor.schedule(() -> {System.out.println("ThreadPool:" + LocalDateTime.now());
}, 1L, TimeUnit.SECONDS);
System.out.println("CurrentTime:" + LocalDateTime.now());

6.WorkStealingPool 使用

Java 8 新增的创建线程池的方式,可根据当前电脑 CPU 处理器数量生成相应个数的线程池,使用代码如下:

ExecutorService workStealingPool = Executors.newWorkStealingPool();
for (int i = 0; i < 5; i++) {int finalNumber = i;workStealingPool.execute(() -> {System.out.println("I:" + finalNumber);});
}
Thread.sleep(5000);

以上程序执行结果如下:

I:0I:3I:2I:1I:4

根据执行结果可以看出,newWorkStealingPool 是并行处理任务的,并不能保证执行顺序。

ThreadPoolExecutor VS Executors
  ThreadPoolExecutor 和 Executors 都是用来创建线程池的,其中 ThreadPoolExecutor 创建线程池的方式相对传统,而 Executors 提供了更多的线程池类型(6 种),但很不幸的消息是在实际开发中并不推荐使用 Executors 的方式来创建线程池。

笔试面试题

1.以下程序会输出什么结果?

public static void main(String[] args) {ExecutorService workStealingPool = Executors.newWorkStealingPool();for (int i = 0; i < 5; i++) {int finalNumber = i;workStealingPool.execute(() -> {System.out.print(finalNumber);});}
}

A:不输出任何结果
B:输出 0 到 9 有序数字
C:输出 0 到 9 无需数字
D:以上全对

答:A
题目解析:newWorkStealingPool 内部实现是 ForkJoinPool,它会随着主程序的退出而退出,因为主程序没有任何休眠和等待操作,程序会一闪而过,不会执行任何信息,所以也就不会输出任何结果。

2.Executors 能创建单线程的线程池吗?怎么创建?

答:Executors 可以创建单线程线程池,创建分为两种方式:

  • Executors.newSingleThreadExecutor():创建一个单线程线程池。
  • Executors.newSingleThreadScheduledExecutor():创建一个可以执行周期性任务的单线程池。

3.Executors 中哪个线程适合执行短时间内大量任务?

答:newCachedThreadPool() 适合处理大量短时间工作任务。它会试图缓存线程并重用,如果没有缓存任务就会新创建任务,如果线程的限制时间超过六十秒,则会被移除线程池,因此它比较适合短时间内处理大量任务。

4.可以执行周期性任务的线程池都有哪些?

答:可执行周期性任务的线程池有两个,分别是:newScheduledThreadPool() 和 newSingleThreadScheduledExecutor(),其中 newSingleThreadScheduledExecutor() 是 newScheduledThreadPool() 的单线程版本。

5.JDK 8 新增了什么线程池?有什么特点?

答:JDK 8 新增的线程池是 newWorkStealingPool(n),如果不指定并发数(也就是不指定 n),newWorkStealingPool() 会根据当前 CPU 处理器数量生成相应个数的线程池。它的特点是并行处理任务的,不能保证任务的执行顺序。

6.newFixedThreadPool 和 ThreadPoolExecutor 有什么关系?

答:newFixedThreadPool 是 ThreadPoolExecutor 包装,newFixedThreadPool 底层也是通过 ThreadPoolExecutor 实现的。

newFixedThreadPool 的实现源码如下:

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

7.单线程的线程池存在的意义是什么?

答:单线程线程池提供了队列功能,如果有多个任务会排队执行,可以保证任务执行的顺序性。单线程线程池也可以重复利用已有线程,减低系统创建和销毁线程的性能开销。

8.线程池为什么建议使用 ThreadPoolExecutor 创建,而非 Executors?

答:使用 ThreadPoolExecutor 能让开发者更加明确线程池的运行规则,避免资源耗尽的风险

Executors 返回线程池的缺点如下:

  • FixedThreadPool 和 SingleThreadPool 允许请求队列长度为 Integer.MAX_VALUE,可能会堆积大量请求,可能会导致内存溢出;
  • CachedThreadPool 和 ScheduledThreadPool 允许创建线程数量为 Integer.MAX_VALUE,创建大量线程,可能会导致内存溢出。

Java笔试面试-Executors相关推荐

  1. 修作玉颜色,卖于帝王家(java笔试面试—-求职经历)

    文时至今日方才起笔,不知为何,曾经在奔跑的过程中,无数次的提醒自己,等正式卖完身之后一定要写下这篇文章,来纪念过去的时日,一为警惕自身,二为温馨提示后人.但已经卖身快两个月了,还是无法真正地写下一纸半 ...

  2. Java笔试面试总结—try、catch、finally语句中有return 的各类情况

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 前言 之前在刷笔试题和面试的时候经常会遇到或者被问到 tr ...

  3. java笔试面试经典问题

    java面试笔试题大汇总 JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题 ...

  4. Java笔试面试(社招版)

    一.并发 Java面试–线程池 Java面试–ThreadLocal Java面试–乐观锁和悲观锁 Java面试–线程的生命周期状态 Java面试–Synchronized Java面试–wait和s ...

  5. Java笔试面试-克隆和序列化

    克隆 1.浅克隆 默认的 clone() 方法,为浅克隆,代码如下: class CloneTest {public static void main(String[] args) throws Cl ...

  6. Java笔试面试练习题---集合

    一.单选题 1.ArrayList类的底层数据结构是( A ) A.数组结构 B.链表结构 C.哈希表结构 D.红黑树结构 解析:ArrayList底层的实现就是一个数组(固定大小),当数组长度不够用 ...

  7. Java笔试面试-设计模式

    1.说一下设计模式?你都知道哪些? 答:设计模式总共有 23 种,总体来说可以分为三大类:创建型模式( Creational Patterns ).结构型模式( Structural Patterns ...

  8. Java笔试面试-JVM

    1.什么是 JVM?它有什么作用? 答:JVM 是 Java Virtual Machine(Java 虚拟机)的缩写,顾名思义它是一个虚拟计算机,也是 Java 程序能够实现跨平台的基础.它的作用是 ...

  9. Java笔试面试-Java 分布式框架面试总结

    1.什么是 ZooKeeper? 答:ZooKeeper 是一个开源的分布式应用程序协调服务,是一个典型的分布式数据一致性解决方案.设计目的是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高 ...

最新文章

  1. PHPUnit实践三(构建模块化的测试单元)
  2. 爬虫-scrapy的中间件
  3. 程序员常犯的五个非技术性错误
  4. SpringBoot集成OpenOffice实现doc文档转html
  5. TCP/IP 体系结构
  6. 《Python Cookbook 3rd》笔记(3.8):分数运算
  7. 信息学奥赛一本通 1031:反向输出一个三位数 | OpenJudge NOI 1.3 13
  8. mysql数据库复制功能配置,最详细的mysql数据库主从复制功能配置教程(docker版本)...
  9. 关于visio你必须要知道的一些小技巧
  10. iOS开发-使用Storyboard进行界面跳转及传值
  11. 开心网(kaixin001.com)服务器架构的一点猜想
  12. inline-block从入门到精通
  13. 模拟电子技术基础_童诗白、华成英(第五版)目录
  14. SPSS、 Mplus下载安装包
  15. python安装time模块_Python之路-Python常用模块-time模块
  16. 使用OpenSSL自建CA及颁发证书、吊销证书
  17. IPv6路由信息的序号
  18. 苹果手机换电池对手机有影响吗_你知道你的手机电池多久换一次吗?
  19. 近年来Person Re-identification论文汇总
  20. 数值法求解最优控制问题(四)——伪谱法

热门文章

  1. 如何检测文章被搜索引擎收录(如何让搜索引擎收录网站)
  2. mysql 空闲链接超时时间_解决mysql 中共8小时空闲后连接超时的有关问题
  3. 绿色智慧档案馆构想之智慧档案馆环境综合管控一体化平台
  4. Android原生webView概述
  5. 【数据科学】斯皮尔曼的等级相关系数(Spearman's coefficient)
  6. 汉语拼音工具包相关实用方法
  7. 电脑充电器,电脑充电器没带怎么充电
  8. 双螺杆挤出机有哪些系列
  9. ~ 如何用C++自制一个日麻游戏 ~(一)大体框架构建 § 2 数据结构
  10. java 数组的行数和列数