Java 中的几种线程池,你之前用对了吗,互联网 面试官 如何面试

互联网大厂Java面试真相揭秘:严肃面试官VS搞笑谢飞机 谢飞机:哦,这是个技术名词,应该是和锁差不多吧?面试官:CAS是无锁的线程安全机制,通过比较并交换操作保证原子更新,减少线程阻塞。 阅读详情


写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。扫码加微信好友进【程序员面试学习交流群】,免费领取。也欢迎各位一起在群里探讨技术。

 

 

好久不发文章了,难道是因为忙,其实是因为懒。这是一篇关于线程池使用和基本原理的科普水文,如果你经常用到线程池,不知道你的用法标准不标准,是否有隐藏的 OOM 风险。不经常用线程池的同学,还有对几种线程的使用不甚了解的同学可以读一下此文。


 

 

为什么要使用线程池

虽然大家应该都已经很清楚了,但还是说一下。其实归根结底最主要的一个原因就是为了提高性能。

线程池和数据库连接池是同样的道理,数据库连接池是为了减少连接建立和释放带来的性能开销。而线程池则是为了减少线程建立和销毁带来的性能消耗。

以 web 项目为例,有以下两种情况:

1、每次过来一个请求,都要在服务端创建一个新线程来处理请求,请求处理完成销毁线程;

2、每次过来一个请求,服务端在线程池中直接拿过一个空闲的线程来处理这个请求,处理完成后还给线程池;

答案是肯定的,肯定是第二种使用线程池的方式性能更好。

除了性能这个最重要的原因外,线程池的使用可以帮助我们更合理的使用系统资源。还是以 web 项目为例,如果我们在服务端不使用线程池,而是无节制的来一个请求创建一个线程,系统资源将会很快被耗尽。而使用线程池的话,则可以防止这种情况发生,当然这要建立在正确合理的使用线程池的基础上,要固定线程的最大数以及等待队列的大小。

几种线程池的使用和原理

线程池固然好用,但是要建立在正确的使用方式的基础上,如果使用方式不当,同样会出现问题。接下来就介绍一下几种线程池的使用。

在大名鼎鼎的 J.U.C 包下已经提供了 Executors 类,它已经封装实现了四种创建线程池的方式,它暴露出几个简单的方法供开发者调用。最终都是通过 new ThreadPoolExecutor() ExecutorService 实例,从而得到我们想要的线程池类型。这样做其实有利有弊,好的是我们不用关心那么多参数,只需要简单的指定一两个参数就可以;不好的是,这样一来又屏蔽了很多细节,如果有些参数使用默认的,而开发者又不了解原理的情况下,可能会造成 OOM 等问题。

很多公司都不建议或者强制不允许直接使用 Executors 类提供的方法来创建线程池,例如阿里巴巴Java开发手册里就明确不允许这样创建线程池,一定要通过 ThreadPoolExecutor(xx,xx,xx...) 来明确线程池的运行规则,指定更合理的参数。

先来看一下 ThreadPoolExecutor 的几个参数和它们的意义,先来看一下它最完整参数的重载。

public ThreadPoolExecutor(int corePoolSize,

                              int maximumPoolSize,

                              long keepAliveTime,

                              TimeUnit unit,

                              BlockingQueue<Runnable> workQueue,

                              ThreadFactory threadFactory,

                              RejectedExecutionHandler handler)

一共有 7 个参数。

corePoolSize

核心线程数,当有任务进来的时候,如果当前线程数还未达到 corePoolSize 个数,则创建核心线程,核心线程有几个特点:

1、当线程数未达到核心线程最大值的时候,新任务进来,即使有空闲线程,也不会复用,仍然新建核心线程;

2、核心线程一般不会被销毁,即使是空闲的状态,但是如果通过方法 allowCoreThreadTimeOut(boolean value) 设置为 true 时,超时也同样会被销毁;

3、生产环境首次初始化的时候,可以调用 prestartCoreThread() 方法来预先创建所有核心线程,避免第一次调用缓慢;

maximumPoolSize

除了有核心线程外,有些策略是当核心线程完全无空闲的时候,还会创建一些临时的线程来处理任务,maximumPoolSize 就是核心线程 + 临时线程的最大上限。临时线程有一个超时机制,超过了设置的空闲时间没有事儿干,就会被销毁。

keepAliveTime

这个就是上面两个参数里所提到的超时时间,也就是线程的最大空闲时间,默认用于非核心线程,通过 allowCoreThreadTimeOut(boolean value) 方法设置后,也会用于核心线程。

unit

这个参数配合上面的 keepAliveTime ,指定超时的时间单位,秒、分、时等。

workQueue

等待执行的任务队列,如果核心线程没有空闲的了,新来的任务就会被放到这个等待队列中。这个参数其实一定程度上决定了线程池的运行策略,为什么这么说呢,因为队列分为有界队列和无界队列。

有界队列:队列的长度有上限,当核心线程满载的时候,新任务进来进入队列,当达到上限,有没有核心线程去即时取走处理,这个时候,就会创建临时线程。(警惕临时线程无限增加的风险)

无界队列:队列没有上限的,当没有核心线程空闲的时候,新来的任务可以无止境的向队列中添加,而永远也不会创建临时线程。(警惕任务队列无限堆积的风险)

threadFactory

它是一个接口,用于实现生成线程的方式、定义线程名格式、是否后台执行等等,可以用 Executors.defaultThreadFactory() 默认的实现即可,也可以用 Guava 等三方库提供的方法实现,如果有特殊要求的话可以自己定义。它最重要的地方应该就是定义线程名称的格式,便于排查问题了吧。

handler

当没有空闲的线程处理任务,并且等待队列已满(当然这只对有界队列有效),再有新任务进来的话,就要做一些取舍了,而这个参数就是指定取舍策略的,有下面四种策略可以选择:

ThreadPoolExecutor.AbortPolicy:直接抛出异常,这是默认策略; 

ThreadPoolExecutor.DiscardPolicy:直接丢弃任务,但是不抛出异常。 

ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后将新来的任务加入等待队列

ThreadPoolExecutor.CallerRunsPolicy:由线程池所在的线程处理该任务,比如在 main 函数中创建线程池,如果执行此策略,将有 main 线程来执行该任务

虽然并不提倡用 Executors 中的方法来创建线程池,但还是用他们来讲一下几种线程池的原理。

1、newFixedThreadPool

它有两个重载方法,代码如下:

public static ExecutorService newFixedThreadPool(int nThreads) {

        return new ThreadPoolExecutor(nThreads, nThreads,

                                      0L, TimeUnit.MILLISECONDS,

                                      new LinkedBlockingQueue<Runnable>());

}

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {

        return new ThreadPoolExecutor(nThreads, nThreads,

                                      0L, TimeUnit.MILLISECONDS,

                                      new LinkedBlockingQueue<Runnable>(),

                                      threadFactory);

 }

    

建立一个线程数量固定的线程池,规定的最大线程数量,超过这个数量之后进来的任务,会放到等待队列中,如果有空闲线程,则在等待队列中获取,遵循先进先出原则。

创建固定线程数量线程池, corePoolSize 和 maximumPoolSize 要一致,即核心线程数和最大线程数(核心+非核心线程)一致,Executors 默认使用的是 LinkedBlockingQueue 作为等待队列,这是一个无界队列,这也是使用它的风险所在,除非你能保证提交的任务不会无节制的增长,否则不要使用无界队列,这样有可能造成等待队列无限增加,造成 OOM。

正确的创建固定线程数线程池的做法是

private static ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("fengzheng" + "-%d").setDaemon(true).build();

public static ExecutorService createFixedThreadPool() {

        int poolSize = 5;

        int queueSize = 10;

        ExecutorService executorService = new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.SECONDS,

                new ArrayBlockingQueue<Runnable>(queueSize), threadFactory, new ThreadPoolExecutor.AbortPolicy());

        return executorService;

    }

上面代码是创建一个 5 个线程的固定数量线程池,这里线程存活时间没有作用,所以设置为 0,使用了 ArrayBlockingQueue 作为等待队列,设置长度为 10 ,最多允许10个等待任务,超过的任务会执行默认的 AbortPolicy 策略,也就是直接抛异常。ThreadFactory 使用了 Guava 库提供的方法,定义了线程名称,方便之后排查问题。

2、newSingleThreadExecutor

建立一个只有一个线程的线程池,如果有超过一个任务进来,只有一个可以执行,其余的都会放到等待队列中,如果有空闲线程,则在等待队列中获取,遵循先进先出原则。使用 LinkedBlockingQueue 作为等待队列。

这个方法同样存在等待队列无限长的问题,容易造成 OOM,所以正确的创建方式参考上面固定数量线程池创建的方式,只是把 poolSize 设置为 1 。

3、newCachedThreadPool

缓存型线程池,在核心线程达到最大值之前,有任务进来就会创建新的核心线程,并加入核心线程池,即时有空闲的线程,也不会复用。达到最大核心线程数后,新任务进来,如果有空闲线程,则直接拿来使用,如果没有空闲线程,则新建临时线程。并且线程的允许空闲时间都很短,如果超过空闲时间没有活动,则销毁临时线程。关键点就在于它使用 SynchronousQueue 作为等待队列,它不会保留任务,新任务进来后,直接创建临时线程处理,这样一来,也就容易造成无限制的创建线程,造成 OOM。

正确的创建缓存型线程池的做法是

private static ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("fengzheng" + "-%d").setDaemon(true).build();

    public static ExecutorService createCacheThreadPool(){

        int coreSize = 10;

        int maxSize = 20;

        return new ThreadPoolExecutor(coreSize, maxSize, 10L, TimeUnit.SECONDS,

                new SynchronousQueue<Runnable>(), threadFactory, new ThreadPoolExecutor.AbortPolicy());

    }

4、newScheduledThreadPool

计划型线程池,可以设置固定时间的延时或者定期执行任务,同样是看线程池中有没有空闲线程,如果有,直接拿来使用,如果没有,则新建线程加入池。使用的是 DelayedWorkQueue 作为等待队列,这中类型的队列会保证只有到了指定的延时时间,才会执行任务。

正确的创建缓存型线程池的做法是

private static ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("fengzheng" + "-%d").setDaemon(true).build();

    private static CountDownLatch latch = new CountDownLatch(1);

    public static void main(String[] args) throws InterruptedException {

        Task task = new Task();

        ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(2, threadFactory);

        executorService.scheduleAtFixedRate(task,0L,5L, TimeUnit.SECONDS);

        latch.await();

    }

    static class Task implements Runnable{

        @Override

        public void run() {

            System.out.println(Thread.currentThread().getName() + "executing");

        }

    }

最后,各位同学不妨到我的公众号里互动一下 : 古时的风筝 ,进入公众号可以加入交流群

扫码关注

 


转载:https://www.cnblogs.com/fengzheng/p/9297602.html

推荐内容:
Java面试经
Java常见面试题一
java实现邮箱发送邮件功能
Java面试题:小白不得不懂的斐波那契数列
java后端面试
转载:[Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)
Java简历与面试
100道Java基础面试题
【JAVA面试】java面试题整理(4)
Java面试前需要了解的东西

 

互联网大厂Java面试故事:严肃面试官与搞笑水货程序员谢飞机的较量 在一家知名互联网大厂的Java程序员面试现场,严肃的面试官与搞笑的水货程序员谢飞机展开了激烈而趣味横生的技术问答。通过3轮循序渐进的问题,面试官考察了谢飞机在Java核心知识、JUC、JVM、多线程、线程池、Spring等众多技术领域的掌握程度。本文不仅展现了面试现场的真实情境,还附带详细答案解析,助力小白学习。 阅读详情

相关推荐

战舰V3移植CANopenNode并驱动电机全流程

第三部分是电机的对象字典(也就是节点的OD)中的索引,长度2个字节。索引发送的是小段模式,比如这一部分为0X40 0X60,实际操作的索引地址为0X6040。第一部分是COB-ID,长度1个字节,电机的node-ID默认为0x01,所以报文ID一直是601。第五部分是要写入的数据,数据发送的时候是小端模式,低字节数据先发送,长度由第二部分决定。配置定时器6,时间为1ms,根据公式计算得到参数PSC取72-1,ARR取1000-1。第二部分是CMD,长度1个字节,其实就是数据部分的长度,

qq_50526837的博客 3045

Java 中的几种线程池,你之前用对了吗

好久不发文章了,难道是因为忙,其实是因为懒。这是一篇关于线程池使用和基本原理的科普水文,如果你经常用到线程池,不知道你的用法标准不标准,是否有隐藏的 OOM 风险。不经常用线程池的同学,还有对几种线程的使用不甚了解的同学可以读一下此文。 为什么要使用线程池 虽然大家应该都已经很清楚了,但还是说一下。其实归根结底最主要的一个原因就是为了提高性能。 线程池和数据库连接池是同样的道理,数据库连接池是...

weixin_34174322的博客 175

高阶玩法——Dify生成的数据自动写入mysql数据库

采用自定义工具方式,利用 python编写一个服务sql_save_post,将接收到的内容写入指定数据库的表中,并为该服务撰写一个 OpenAPI 的 schema。配置工作流:我们以写入天气预报为例,在生成天气预报内容后,连接自定义工具“sql_save_post”,将所需的字段配置完成后,实现将生成的内容自动写入mysql数据库中。编写OpenAPI的schema:在dify平台的工具栏目,创建自定义工具,输入工具名称“sql_save_post”。工具:sql_save_post;

qq_44493378的博客 8539

为什么我们有必要用到java线程池?

谈到java多线程,你还在说 1:new Thread();2: 实现Runnable接口。。。。 如果真的用到多线程,基本上就只用java的线程池,不用线程池的话: 1. 每次new Thread新建对象性能差。 2. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。 3. 缺乏更多功能,如定时执行、定期执行、线程中断。相比new Thread,J...

Alves的博客 9322

Akamai移动端Sensor数据采集与BMP风控机制深度解析

本文深度解析了Akamai在移动端风控中的核心机制,重点阐述了Sensor数据如何通过采集陀螺仪、加速度计等硬件信息,结合设备指纹生成连续且符合物理规律的行为轨迹。详细剖析了数据从采集、加密校验到通过BMP风控三重验证(校验位、时间差、数据逻辑)的完整流程,并提供了从模拟优化到自建风控模型的实用应对思路。

quiet的专栏 284

配置xen上VM混杂模式,使其能捕获物理网络流量

本文目的:配置VM和xen相应的物理网卡(pif)和虚拟网卡(vi

LeoDuo的专栏 3720

面试突击:线程池有几种创建方式?推荐使用哪种?

在 Java 语言中,并发编程都是通过创建线程池来实现的,而线程池的创建方式也有很多种,每种线程池的创建方式都对应了不同的使用场景,总体来说线程池的创建可以分为以下两类: 通过 ThreadPoolExecutor 手动创建线程池。 通过 Executors 执行器自动创建线程池。 而以上两类创建线程池的方式,又有 7 种具体实现方法,这 7 种实现方法分别是: Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。.

HongYu012的博客 1万+

深入理解HanLP1.x,填平可能遇到的坑

提取指定数量的摘要。自定义词典为什么要单独领出来讲呢?因为在我们的业务开发中,可能分词的效果并不理想,需要定制自己的词库,索引更加常用。例如:小米su7特斯拉modelY比亚042025款6575767670908我们需要分出小米su72025款等词。我们分别看看用字典和不用字典的效果。

static_coder的博客 977

【java面试】精讲!面试被问Java官方提供了哪几种线程池,分别有什么特点?

这个问题考察大家对于线程池的基本认识。平时使用得比较少的同学可以好好学习一下线程池的底层原理然后再去理解JDK官方提供的几个线程池的实现。就可以随时回答出这个问题了。另外,我将所有Java面试系列制作成了完整的面试文档。它的便捷之处在于,可以通过检索的方式,找到你想要的面试题,目前已经更新180期,总计超过15W字!

跟着Mic学架构 585

Mac上除了Homebrew,这几种安装ADB的方法你可能也需要知道(含手动配置避坑)

本文全面解析Mac上五种ADB安装方案,从Homebrew到手动配置,涵盖常见问题解决与环境变量配置。特别针对macOS High Sierra等老旧系统提供专属解法,帮助开发者高效安装Android Debug Bridge(ADB),避免常见陷阱,提升开发效率。

weixin_42546392的博客 322

基于Python的电商平台商品信息爬取与价格监控系统设计与实现

本文详细介绍了一个基于Python的电商平台商品信息爬取与价格监控系统的设计与实现。系统采用最新的Python爬虫技术栈,包括Scrapy框架、Selenium自动化测试工具、BeautifulSoup解析库等,实现了对主流电商平台商品信息的自动化采集、存储、分析和可视化展示。文章从系统架构设计、关键技术实现、核心代码解析等方面进行了全面阐述,并提供了完整的代码实现。该系统不仅适用于毕业设计,也可作为商业价格监控系统的原型。关键词:Python爬虫;电商数据采集;价格监控;Scrapy;Selenium;

2201_76125261的博客 963

Java线程池以及阿里为什么不推荐使用Java自带的线程池和解决方法

Java线程池以及为什么不推荐使用Java自带的线程池

ZhAoYaJ的博客 4561

华为Ascend_toolkit在x86ubuntu安装失败报错。[WARNING] driver package is not installed. If you install in docker

这个报错发生在交叉编译配置Ascend_toolkit环境时,安装Ascend_toolkit安装包的时候发生。[Y/N]Y。

anananajiushiwo的博客 1019

互联网大厂Java面试实录:严肃面试官PK搞笑水货程序员谢飞机

在互联网大厂的Java岗位面试中,技术问题层出不穷。本文通过一场真实的面试对话,展现了面试官与求职者谢飞机之间的问答互动,涵盖Java核心知识、JUC、JVM、多线程、线程池、HashMap、ArrayList、Spring、SpringBoot、MyBatis、Dubbo、RabbitMQ、xxl-job、Redis、MySQL、Linux、Docker、设计模式、DDD等多项技术点。

qq_36486078的博客 1698

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

互联网大厂Java面试故事:严肃面试官vs搞笑谢飞机的三轮提问

请你简述一下Java中的内存模型以及JVM的基本结构。嗯,Java有堆和栈还有方法区,内存分很多区域,JVM有类加载器、运行时数据区和执行引擎这些部分。很好,回答得很准确。那你说说HashMap和ArrayList的区别。哈哈,HashMap是用来存键值对的,ArrayList是用来存一堆对象的数组。不错,简洁明了。那对于多线程,你知道Java中线程的状态有哪些吗?线程状态?有新建、运行、阻塞、等待、计时等待和终止这些。回答得非常全面。

m0_62482497的博客 1760

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

面试官与水货程序员张三的互联网大厂Java面试三轮问答实录

本文以故事形式展现互联网大厂Java面试现场,面试官严肃提问,水货程序员张三机智又搞笑地应答。每轮提问层层递进,文末附详细答案解析,助你面试一臂之力!

qq_41780196的博客 1628

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

互联网大厂Java面试实录:严肃面试官与搞笑程序员的对决

JVM(Java Virtual Machine)是Java语言的运行环境,负责将Java字节码转换为机器码执行,并管理内存、线程、垃圾回收等。线程池管理一组工作线程,用于执行异步任务,减少了线程创建和销毁的开销。Java内存模型(JMM)定义了Java虚拟机在多线程环境下对内存的管理方式,确保线程间的内存可见性和有序性。:JVM就是Java的家,相当于我们程序员的电脑主机,管吃管住。:内存模型就是JVM的卧室、厨房、客厅,负责处理不同的家务活。面试官:好的,今天的面试就到这里,回去等通知吧。

qq_54743734的博客 815

互联网大厂Java面试实录:严肃面试官与水货程序员谢飞机的对决

谢飞机,先简单介绍一下ArrayList和LinkedList的区别吧。:啊?ArrayList是数组,LinkedList是链表,一个快一个慢,对吧?(点头):不错,ArrayList基于动态数组,查询快但增删慢;LinkedList基于双向链表,增删快但查询慢。:HashMap的底层原理是什么?:嗯……就是键值对,用哈希表存的?(微笑):对,但更详细一点,HashMap在JDK8后是数组+链表+红黑树的结构,哈希冲突时用链表,链表过长转红黑树。:线程安全的集合有哪些?

java_rutu的博客 1789

互联网大厂Java面试实录:严肃面试官遇见搞笑水货程序员谢飞机

在互联网大厂的Java面试中,面试官遇到了一个既严肃又搞笑的水货程序员——谢飞机。三轮的面试问答中,面试官针对Java核心知识、JUC、JVM、多线程等技术逐步深入提问,而谢飞机有板有眼地答对了简单问题,赢得了面试官的称赞;遇到难题时则表现得略显糊涂。本文记录了这场充满技术与趣味的面试实录,并在最后详细解答所有问题,帮助读者学习。

2301_76443258的博客 786

互联网大厂Java面试奇遇记

面试官一脸严肃地看着谢飞机,推了推眼镜说道:“谢飞机是吧,咱们开始面试。先问几个Java基础的问题。

weixin_42296490的博客 1839

互联网大厂Java面试实录:面试官与程序员张三的爆笑对话

某互联网大厂的Java面试现场,面试官严肃冷静,程序员张三略带戏谑。在三轮技术问答中,面试官步步为营,涵盖Java核心、JUC、JVM、Spring、MyBatis、Dubbo、数据库、消息队列等各类主流技术。张三遇到简单问题能应付自如,遇到难题则胡乱作答,场面极具喜感。

qq_41780196的博客 1489

互联网大厂Java求职面试实录 —— 严肃面试官遇到搞笑水货程序员

本文以真实场景还原的互联网大厂Java面试故事,严肃的面试官与搞笑的水货程序员谢飞机的对话形式,涵盖核心Java、JUC、多线程、线程池、SpringBoot、MyBatis、Dubbo、RabbitMQ、xxl-job、Redis、MySQL、Linux、Docker、设计模式、DDD等热门技术,附代码示例,技术解读。适合求职者和Java小白学习。

优快云_LiMingfly的博客 1143

互联网大厂Java求职面试故事:严肃面试官VS搞笑水货程序员李三

此次面试在一家知名互联网大厂进行。面试官严肃认真,追求技术细节完美;李三作为一名水货程序员,回答问题时时而靠谱,时而搞笑让人哭笑不得。

paopaotui的博客 1587

互联网大厂Java面试故事:严肃面试官VS搞笑谢飞机的三轮问答

分布式任务调度框架,支持任务管理、执行和监控。这场面试的故事,既有谢飞机的幽默,也有技术的深度,希望能帮助Java求职者更好地准备面试。

qq_43511085的博客 634

互联网大厂Java面试实录:李某某的奇幻面试旅程

在一个阳光明媚的早晨,李某某走进了某互联网大厂的面试间,准备接受一场关于Java技术的洗礼。:ReentrantLock是一个显式锁,可以更灵活地控制锁的获取和释放,而synchronized是隐式锁,使用更简单,但功能较少。:HashMap基于数组和链表实现,通过哈希函数计算键的哈希值,将其映射到数组的索引位置。:哦,当然,ReentrantLock是一个高级的锁,synchronized是个……:一级缓存是SqlSession级别的缓存,二级缓存是Mapper级别的缓存,存储在内存中。

qq_34968019的博客 1902

互联网大厂Java面试揭秘:笑料百出的谢飞机与严肃面试官的对决

谢飞机,你能简单介绍一下Java的内存模型吗?Java的内存模型就是JVM的内存布局嘛,有堆、栈、方法区之类的,对吧?嗯,回答得不错。那么你了解过JUC(Java并发工具包)吗?JUC?就是一些并发工具,比如CountDownLatch、CyclicBarrier,用来控制线程同步的,对吧?很好,那你能解释一下JVM内存分配的原理吗?JVM内存分配嘛,就是给对象分配内存,有新生代、老年代这些区分,对吧?好的,接下来我们谈谈多线程编程,你觉得Thread和Runnable接口有什么区别?

zsl123456_的博客 1335
上一篇: Java性能优化之String字符串优化,BAT 面试官 如何面试
下一篇: Java 小记 — Spring Boot 的实践与思考,互联网 面试官 如何面试
agoodcoder777
博客等级 码龄8年 24粉丝 54原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值