当前位置:首页 > 服务端 > Java坑人面试题系列: 线程/线程池(高级难度)

Java坑人面试题系列: 线程/线程池(高级难度)

2022年11月07日 08:50:30服务端6

点击上方“Java后端技术栈“关注

持续推送技术干货

Java坑人面试题系列: 线程/线程池(高级难度) _ JavaClub全栈架构师技术笔记

ExecutorService 接口及相关API细节详解。

这些问题的设计宗旨,主要是测试面试者对Java语言的了解程度,而不是为了用弯弯绕绕的手段把面试者搞蒙。

如果你看过往期的问题,就会发现每一个都不简单。

这些试题模拟了认证考试中的一些难题。而 “中级(intermediate)” 和 “高级(advanced)” 指的是试题难度,而不是说这些知识本身很深。一般来说,“高级”问题会稍微难一点。

问题(高级难度)此问题的目的是考察如何通过 Runnable 和 Callable 来创建任务,并使用 ExecutorService 来并发执行。

我们有一个 Logger 类,定义如下所示:

class Logger implements Runnable {
    String msg;
    public Logger(String msg) {
        this.msg = msg;
    }
    public void run() {
        System.out.print(msg);
    }
}

并给出如下使用的代码:

Stream<Logger> s = Stream.of(
    new Logger("Error "),
    new Logger("Warning "),
    new Logger("Debug "));
ExecutorService es = Executors.newCachedThreadPool();
s.sequential().forEach(l -> es.execute(l));        
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);

这里省略了相关的 import 语句, 假设代码能编译并正常启动。请选择两项可能的输出结果:

A、 Error Debug Warning
B、 Error Warning Debug
C、 Error Error Debug
D、 Error Debug

答案和解析这道试题属于 Executors 类和 ExecutorService接口相关的考点,顺带考察 Executors 工具类自带的 ExecutorService线程池实现。

在Java的早期版本中,需要程序员手工创建和管理线程。线程是系统内核级的重要资源,并不能无限创建; 而且创建线程的开销很大,所以开发中一般会使用资源池模式,也就是创建 “线程池”。通过线程池,可以用少量的线程,来执行大量的任务。线程池的思路是这样的:与其为每个任务创建一个线程,执行完就销毁;倒不如统一创建少量的线程, 然后将任务逻辑用 Runnable 包装起来, 提交给线程池来调度执行。有任务需要调度的时候,线程池找一个空闲的线程,并通知他干活。任务执行完成后,再将这个线程放回池子里,等待下一次调度。

Java 5.0 开始提供标准的线程池API。通过 Executor 和 ExecutorService接口定义了线程池以及支持的交互操作。另外,我们可以使用 Executors 的静态工厂方法来实例化 ExecutorService的各种实现。相关的基础类和接口都位于 java.util.concurrent包中, 在编写简单的并发任务时,可以直接使用。

Executor 是顶层接口, 定义了执行 Runnable 任务的方法;但我们一般用的是子接口 ExecutorService及其实现。ExecutorService接口中增加了处理 Callable 的方法, 以及关闭线程池的功能。实现 Callable 接口的任务会返回一个结果, 调用方可以通过提交任务时返回的 Future 对象,来异步获取任务的执行状态和结果,这样就对任务有了一定的管理和控制能力。

Executor 和 ExecutorService接口并没有规定使用哪种调度策略来执行。

  • 有些线程池,使用固定数量的线程来并发地执行任务,新提交的任务要等到有空闲线程才会被执行。

  • 有的线程池, 在工作负载上升时自动增加线程,并在需求降低时清理掉一部分线程。

  • 还有的线程池只使用单个线程,直接按顺序执行提交的任务。

这些特征取决于具体的实现,需要开发者根据业务系统的特征来权衡,并选择适当的线程池。针对这几类线程池,Executors 工具类提供了三种工厂方法:

  • newFixedThreadPool

  • newCachedThreadPool

  • newSingleThreadExecutor

前两个方法创建的线程池可以有多个worker线程, 而 newSingleThreadExecutor方法创建的线程池则只有单个线程。

回到前面的问题, 试题中给出的代码创建了缓存模式的线程池。这类线程池会根据需要生成新的worker线程,并清理一段时间内没有使用到的线程。但缓存模式的线程池有一个严重缺点:创建的线程数有可能不被限制, 那样的话会导致大量的资源占用。在高负载场景下,可能会由于资源争用而导致性能急剧下降。

因为创建的线程池具有多个线程, 所以后面提交的任务可以并发执行。无论谁先开始,我们都无法对其执行进度做出精确预测。也就是说,他们输出消息的顺序可能是任意的。

由此得知, 选项A 和 选项B 都 正确。

ExecutorService会保证提交的任务最多被执行一次。在某些情况下,任务可能不会执行,或者在执行完成之前线程池就被关闭了。因为具有最多执行一次的特征,所以我们不会看到任何重复的消息。因此可以判断,选项C不正确。

在调用 shutdown 方法之后,ExecutorService会拒绝新的任务提交请求, 但已有的任务会继续运行,直到所有的作业全部执行完才会关闭。因此在这里给的代码中, 三个消息都会看到。因此可知,选项D不正确。

顺便提一句,可能有些读者会认为,如果在10秒内执行不完, 那么选项D也可能是正确的。但反过来说,如何确定这个消息会被打印呢?

因为试题中给出的任务逻辑非常简单,很明显不可能10秒钟还执行不完。而且我们通过分析能判断出 选项A 和 选项B 是正确的, 那么做题时就可以将这种不可能的情况排除。

当然,你可能对选项D感兴趣,因为在其他某些极端的情况下, 作业无法在10秒内完成,比如恰好在这个时刻操作系统启动升级或更新。请注意,在给定的代码中,没有任何证据表明 JVM 将被强行关闭。而且默认创建的线程都是 非守护线程(nondaemon thread),因此,在作业完成之前,JVM 不会退出。

所以,如果允许程序运行,则对应的消息都会被打印出来。

正确的选项是 A 和 B。

原文:https://renfufei.blog.csdn.net/article/details/104726229

往期精选

去 BAT 面试,总结了这 50 道 MySQL 面试题!

在家远程面试,该如何让面试官钟意你?

Spring MVC 面试题和答案

面试被问频率最高的几道Redis面试题

ThreadLocal 面试六连问,中高级必问

Spring Boot系列--面试题和参考答案

面试必问:Spring循环依赖的三种方式

10 大 Java面试难题,打趴无数面试者!

【文章汇总】面试篇

Java坑人面试题系列: 线程/线程池(高级难度) _ JavaClub全栈架构师技术笔记

在这金三银四的季节,栈长为大家准备了四面试宝典:

  • 《java面试宝典5.0》

  • 《Java(BAT)面试必备》

  • 《350道Java面试题:整理自100+公司》

  • 《资深java面试宝典-视频版》

  • 大量电子书籍

分别适用于初中级,中高级,以及资深级工程师的面试复习。

内容包含java基础、javaweb、各个性能优化、JVM、锁、高并发、反射、Spring原理、微服务、Zookeeper、数据库、数据结构、限流熔断降级等等。

Java坑人面试题系列: 线程/线程池(高级难度) _ JavaClub全栈架构师技术笔记

获取方式:点“在看”,V信扫描上面二维码:注明面试领取,更多精彩陆续奉上。

作者:田哥coder
来源链接:https://blog.csdn.net/o9109003234/article/details/105021233/

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/server/68292.html

标签: 面试
分享给朋友:

“Java坑人面试题系列: 线程/线程池(高级难度)” 的相关文章

IOS面试题详解(二)..

IOS面试题详解(二)..

上一篇文章列出了共32道IOS面试题: http://www.cnblogs.com/fkdd/archive/2012/03/13/2394724.html 下面从第一题开始解答: 题目:1.Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?...

分布式专题|肝了这篇,再也不怕面试官问BIO、NIO、AIO了,我先肝了,你随意

分布式专题|肝了这篇,再也不怕面试官问BIO、NIO、AIO了,我先肝了,你随意

IO模型指的是在网络数据传输过程中,使用什么通道去发送和接收数据,我们常见的有BIO、NIO、AIO(NIO2.0),我接下来会对这些进行详细的介绍 同步/异步/阻塞/非阻塞 到底是什么意思? 同步/异步 指的是你去调用一个方法,如...

干货满满--亲身经历的 Python 面试题

面试范围 这么多家公司的面试取个并集的话,基本上所有能问的大类都问了,诸如 Python 基础,web框架,爬虫,数据库,计算机网络,操作系统,数据结构与算法等。下面我就开始详细说一下各个分类我被问到的面试题,我争取尽量的多记起一些来。 面试...

golang对我有益的文章总集

golang 知识总结:https://www.cnblogs.com/darope/p/14455404.html go 常见面试题整理、金三银四全靠它了:https://www.cnblogs.com/darope/p/14469747.html 工程实践:给函数取一个"好"的名字...

互联网大厂Java面试题:使用无界队列的线程池会导致内存飙升吗?

互联网大厂Java面试题:使用无界队列的线程池会导致内存飙升吗?

引自:“ 石杉的架构笔记”公众号 (1)背景引入   今天跟大家聊一个互联网大厂的Java面试题:使用无界队列的线程池会导致内存飙升吗?   因为在面互联网大厂的时候,一定会问并发,问并发的时候一定会问到线程池,问到线程池一定...

(python)剑指Offer 面试题51:数组中重复的数字

(python)剑指Offer 面试题51:数组中重复的数字

问题描述   在长度为n的数组中,所有的元素都是0到n-1的范围内。 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字。 例如,输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出为2或3。   解题思...

Python面试题总结

谈谈你对Python的理解 Python是一门解释型语言,它就相当于找了个翻译,你说一句话它给计算机翻译一句话;Python也是一门动态类型语言,在声明变量的时候不需要指定数据类型Python还支持多继承(其他语言不支持)Python语言语法简洁、代码编写快但是运行速度比其他语言...

Python 中删除列表元素的三种方法

列表基本上是 Python 中最常用的数据结构之一了,并且删除操作也是经常使用的。 那到底有哪些方法可以删除列表中的元素呢?这篇文章就来总结一下。 一共有三种方法,分别是 remove,pop 和 del,下面来详细说明。 remove L.remov...

100 个基本 Python 面试问题第二部分(21-40)

100 个基本 Python 面试问题第二部分(21-40)

🌊 作者主页:海拥 🌊 作者简介:🏆CSDN全栈领域优质创作者、🥇HDZ核心组成员、🥈蝉联C站周榜前十 🌊 粉丝福利:粉丝群 每周送四本书,每月送各种小礼品(搪瓷杯、抱枕、鼠标垫、马克杯等) 直接跳到末尾 去评论区领书 100 个基本的 Py...

年薪20万的阿里巴巴Python工程师面试题

年薪20万的阿里巴巴Python工程师面试题

     随着人工智能时代的到来,Python工程师的需求量也在与日俱增。现在,很多知名公司都或多或少的在使用Python。而对于Python工程师来说,进入大公司,是一个新的职业起点。目前,国内知乎、网易(游戏)、腾讯(某些网站)、搜狐(...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。