面试宝典进阶之Java线程面试题

news2025/1/18 17:13:51

T1、【初级】线程和进程有什么区别?

(1)线程是CPU调度的最小单位,进程是计算分配资源的最小单位。
(2)一个进程至少要有一个线程。
(3)进程之间的内存是隔离的,而同一个进程中的线程之间是共享内存的。

T2、【初级】线程的创建有哪几种方式?

(1)继承Thread类,重写run方法。
(2)实现Runnable接口,重写run方法。
(3)实现Callable接口,重写call方法,结合Future创建线程。
(4)通过线程池创建。

T3、【初级】创建线程池的几种方式?

(1)使用Executors工具类创建线程池
(2)直接使用底层线程池构造函数创建线程:new ThreadPoolExecuto()

T4、【中级】线程池的参数有哪些?

    // 五参创建
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
	// 七参创建
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        //---
    }

(1)corePoolSize 核心线程数
(2)maximumPoolSize 最大线程数
(3)keepAliveTime 空闲线程存活时间
(4)unit 空闲线程存活时间单位
(5)workQueue 工作队列

  • ArrayBlockingQueue
  • LinkedBlockingQuene
  • SynchronousQuene
  • PriorityBlockingQueue

(6)threadFactory 线程工厂
(7)handler 拒绝策略

  • 第一种拒绝策略是 AbortPolicy,这种拒绝策略在拒绝任务时,会直接抛出异常 RejectedExecutionException (属于RuntimeException),让你感知到任务被拒绝了,于是你便可以根据业务逻辑选择重试或者放弃提交等策略。
  • 第二种拒绝策略是 DiscardPolicy,这种拒绝策略正如它的名字所描述的一样,当新任务被提交后直接被丢弃掉,也不会给你任何的通知,相对而言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失。
  • 第三种拒绝策略是 DiscardOldestPolicy,如果线程池没被关闭且没有能力执行,则会丢弃任务队列中的头结点,通常是存活时间最长的任务,这种策略与第二种不同之处在于它丢弃的不是最新提交的,而是队列中存活时间最长的,这样就可以腾出空间给新提交的任务,但同理它也存在一定的数据丢失风险。
  • 第四种拒绝策略是 CallerRunsPolicy,相对而言它就比较完善了,当有新任务提交后,如果线程池没被关闭且没有能力执行,则把这个任务交于提交任务的线程执行,也就是谁提交任务,谁就负责执行任务。这样做主要有两点好处。
  • 第一点新提交的任务不会被丢弃,这样也就不会造成业务损失。
  • 第二点好处是,由于谁提交任务谁就要负责执行任务,这样提交任务的线程就得负责执行任务,而执行任务又是比较耗时的,在这段期间,提交任务的线程被占用,也就不会再提交新的任务,减缓了任务提交的速度,相当于是一个负反馈。在此期间,线程池中的线程也可以充分利用这段时间来执行掉一部分任务,腾出一定的空间,相当于是给了线程池一定的缓冲期。
理解思路
  • 队列已满,并且超过最大线程数,直接报异常
  • 队列已满,并且超过最大线程数,抛弃新添加的任务
  • 队列已满,并且超过最大线程数,抛弃最老的任务
  • 队列已满,并且超过最大线程数,交给提交任务的线程来执行

T5、【中级】多线程中常用的工具类有哪些?

(1)CountDownLaunch:让某一条线程等待其他线程执行完毕后再执行
(2)CycleBarrier:希望多条线程准备就绪之后,一起开始执行
(3)Condition:当希望指定唤醒某条线程时使用

T6、【中级】线程池都有哪些类型?

(1)缓存型线程池:

ExecutorService executorService = Executors.newCachedThreadPool();

(2)固定长度线程池

ExecutorService executorService = Executors.newFixedThreadPool(10);

(3)可定时执行的线程池

ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);

(4)单线程化线程池

ExecutorService executorService = Executors.newSingleThreadExecutor();
理解思路
  • 定长线程池
  • 变长线程池
  • 单线程池
  • 定时线程池

T7、【中级】线程的状态都有哪些?

线程状态

T8、【中级】synchronized和static synchronized区别?

(1)synchronized是对象锁
(2)static synchronized是类锁

T9、【中级】synchronized与Lock有啥区别?

(1)实现方式不同:synchronized是Java语言内置的关键字,而Lock是一个Java API。

(2)粒度不同:synchronized锁的是整个方法或代码块,而Lock可以只锁定代码的一部分,可以灵活地控制加锁和解锁操作。

(3)可中断性不同:synchronized在获取锁失败时会等待,直到获取锁成功,而Lock可以通过tryLock()方法尝试获取锁,如果获取失败则可以终止等待。

(4)条件变量不同:Lock提供了Condition接口来实现线程之间的协调,而synchronized没有类似的概念。

(5)释放方式不同:synchronized可重入,即同一线程可以重复获取锁并解锁synchronized是自动释放锁。而Lock也可重入,但需要手动管理锁的计数器,Lock需要手动释放锁。

理解记忆
  • synchronized是java内置关键字,自动释放锁,可重入,非公平
  • Lock是接口,手动释放锁,可重入,可公平也可以不公平,默认是不公平
  • synchronized的底层原理是使用了操作系统的互斥对象(mutex)来实现的。

T10、【中级】start()和run()有啥区别?

(1)start()方法来启动线程,真正实现了多线程运行。这时无需等待 run 方法体代码执行完毕,可以直接继续执行下面的代码。
(2)通过调用 Thread 类的 start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。
(3)方法 run()称为线程体,它包含了要执行的这个线程的内容,线程就进入了运行状态,开始运行 run 函数当中的代码。 Run 方法运行结束, 此线程终止。然后 CPU 再调度其它线程。

T11、【初级】wait()和sleep()有啥区别?

(1)调用方式不同:wait()是Object类的方法,可以调用任何对象的wait()方法;而sleep()是Thread类的静态方法,只能调用当前执行线程的sleep()方法。

(2)执行的对象不同:wait()会释放对象锁,线程执行完wait()方法后进入等待池中,只能被其他线程调用notify()或notifyAll()方法唤醒;而sleep()不会释放对象锁,线程暂停一段时间后,会重新进入就绪状态,由操作系统进行调度。

(3)使用方式不同:wait()、notify()和notifyAll()通常用于相互协调的线程之间进行协作,如线程A等待线程B的信号来进行操作;而sleep()通常用于程序中对时间的控制,如在执行某个操作时需要暂停一段时间后再继续执行。

(4)异常处理不同:wait()和sleep()都可以抛出InterruptedException异常,但是InterruptedException异常的含义不同。wait()方法在等待过程中如果线程被中断,则会抛出InterruptedException异常;而sleep()方法在睡眠过程中如果线程被中断,则会清除中断标志位,不会抛出InterruptedException异常。

理解记忆
  • sleep()是静态方法,释放cpu但不释放锁,阻塞到时间了就继续执行
  • wait()是object对象的方法,释放锁,通过notify()唤醒

T12、【初级】notify()和notifyAll()有啥区别?

(1)notify()随机唤醒一条线程;
(2)notifyAll()唤醒全部的线程。

T13、悲观锁和乐观锁有啥区别?

(1)并发控制策略不同:悲观锁采用独占锁(排他锁)的方式,在读写数据之前先获得锁,以保证操作的原子性;而乐观锁采用版本号或时间戳等方式实现数据版本控制,在更新数据之前先检查版本号或时间戳是否一致,以确保在多线程环境下对数据的并发访问正确。

(2)加锁开销不同:悲观锁需要频繁的加锁和解锁,造成了较大的加锁开销和系统资源浪费;而乐观锁只需要在更新操作时进行版本号或时间戳的比较,不需要进行加锁和解锁操作,因此开销较小。

(3)适用场景不同:悲观锁适用于多写少读的情况,例如数据库的更新操作;而乐观锁适用于多读少写的情况,例如缓存中数据的更新。

(4)冲突处理方式不同:悲观锁在获取锁失败时会进入等待队列等待锁的释放,从而避免了数据的冲突问题;而乐观锁在检查版本或时间戳失败时需要回滚事务或重新执行操作,从而处理数据的冲突问题。。

理解记忆
  • 悲观锁,是重锁,是真正使用了锁
  • 乐观锁,是轻量级锁,实际上没有使用锁,而是通过CAS实现的

T14、join和CountDownLatch区别

(1)join:join()是线程对象的成员方法,功能是等待调用join()的线程对象执行完毕,才执行其它的逻辑
(2)CountDownLatch是一种灵活的闭锁实现,它维护了一个计数器,通过计数器控制一个或多个线程等待另一组事件发生,具体控制方法是:CountDownLatch调用countDown方法来递减计数器,表示有一个事件发生了,调用await在计数器为0之前保持阻塞。
(3)区别:
- join()的阻塞原理是不停检查join()所属的线程对象是否存活(也就是线程完全执行完毕),如果存活则让调用join()的线程保持阻塞。
- CountDownLatch的阻塞原理是仅仅关注计数器是否为0,若不为0才保持阻塞,它并不关注持有计数器的其它线程是否完全执行完毕。
显然join()能控制阻塞的范围比CountDownLatch小,且没有CountDownLatch那么灵活。

理解记忆
  • join是线程执行完了,才唤醒
  • CountDownLatch是一个计数器,为0时才唤醒

T15、多线程有哪些特性?

(1)原子性
(2)可见性:保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
(3)有序性:通过synchronized和lock来保证有序性

T16、什么是锁?

锁就是在多线程环境下为保证共享资源健康、线程安全的一种手段。
线程操作某个共享资源之前,先对资源加一层锁,保证操作期间没有其他线程访问资源,当操作完成后,再释放锁。

T17、什么是死锁?

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

T18、怎么避免死锁?

1、避免一个线程同时获取多个锁,如果必须使用多个锁,必须使用相同的加锁顺序。
2、降低锁的使用粒度,尽量保证一个锁只占用一个资源
3、尽可能使用定时锁,例如使用lock.tryLock(timeout)来替代使用内部锁机制

T19、分布式锁实有哪些实现方案?

1、基于数据库(唯一索引)
2、基于缓存(Redis,memcached,tair)
3、基于Zookeeper

T20、你都了解哪些锁?

java锁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1370476.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024阿里云服务器ECS实例全方位介绍_优缺点大全

阿里云服务器ECS英文全程Elastic Compute Service&#xff0c;云服务器ECS是一种安全可靠、弹性可伸缩的云计算服务&#xff0c;阿里云提供多种云服务器ECS实例规格&#xff0c;如经济型e实例、通用算力型u1、ECS计算型c7、通用型g7、GPU实例等&#xff0c;阿里云服务器网aliyu…

EMQX5设置客户端连接认证

文章目录 说明配置客户端连接认证配置1、访问控制-客户端认证-创建2、选择“密码”方式-下一步3、选择“内置数据库”-下一步4、账号类型选择“username”5、密码加密方式选择“plain”6、加盐方式“disable”-创建7、添加客户端连接的账密客户端连接验证 心得 说明 号外&…

CST2024的License服务成功启动,仍报错——“The desired daemon is down...”,适用于任何版本!基础设置遗漏!

CST2024的License服务成功启动&#xff0c;仍报错——“The desired daemon is down…”&#xff0c;适用于任何版本&#xff01;基础设置遗漏&#xff01; CST2024的License服务成功启动后报错 若不能成功启动License服务&#xff0c;有可能是你的计算机名称带中文&#xff…

20240105移远的4G模块EC20在Ubuntu 20.04.6 LTS下使用联通5G卡上网的步骤

20240105移远的4G模块EC20在Ubuntu 20.04.6 LTS下使用联通5G卡上网的步骤 2024/1/5 10:11 缘起&#xff1a;需要在Firefly的AIO-3399J开发板上调试移远的4G模块EC20&#xff08;Android10/11/12&#xff09;&#xff0c;需要现在先测试EC20的好坏&#xff01; 陶老板告诉我找一…

ADS1110负电压采集

先说结论&#xff1a; 无法采集绝对的负电压&#xff08;供电电压范围之外&#xff09;。 ADS1110 16位AD转换问题 ads1110负电压采集 ADS1110是差分输入形式 在数据手册上有一个参数 模拟输入端VIN 的输入电压 最大是VDD0.2 最小是GND-0.2 模拟输入端VIN- 的输入也是这样…

C#PDF转Excel

組件 Spire.Pdf.dll, v7.8.9.0 【注意&#xff1a;版本太低的没有此功能】 在Visual Studio中找到参考&#xff0c;鼠标右键点击“引用”&#xff0c;“添加引用”&#xff0c;将本地路径debug文件夹下的dll文件添加引用至程序。 界面图&#xff1a; 1个label&#xff0c;1…

【服务器数据恢复】FreeNAS+ESXi数据恢复案例

服务器数据恢复环境&#xff1a; 一台服务器&#xff0c;虚拟化系统为esxi&#xff0c;上层使用iSCSI的方式实现FC SAN功能&#xff0c;iSCSI通过FreeNAS构建。 FreeNAS采用了UFS2文件系统&#xff0c;esxi虚拟化系统里有3台虚拟机&#xff1a;其中一台虚拟机安装FreeBSD系统&a…

JAVA面向对象基础-容器

一、泛型 我们可以在类的声明处增加泛型列表&#xff0c;如&#xff1a;<T,E,V>。 此处&#xff0c;字符可以是任何标识符&#xff0c;一般采用这3个字母。 【示例9-1】泛型类的声明 1 2 3 4 5 6 7 8 9 10 class MyCollection<E> {// E:表示泛型; Object[] o…

20240109适配selinux让移远的4G模块EC20在Firefly的AIO-3399J开发板的Android11下跑通

20240109适配selinux让移远的4G模块EC20在Firefly的AIO-3399J开发板的Android11下跑通 2024/1/9 10:46 缘起&#xff1a;使用友善之臂的Android11可以让EC20上网&#xff0c;但是同样的修改步骤&#xff0c;Toybrick的Android11不能让EC20上网。 最后确认是selinux的问题&#…

Linux--防火墙,实验案例:基于区域、服务、端口的访问控制

实验环境 某公司的Web服务器&#xff0c;网关服务器均采用Linux CentOS 7.3操作系统&#xff0c;如图2.13所示。为了 加强网络访问的安全性&#xff0c;要求管理员熟悉firewalld防火墙规则的编写&#xff0c;以便制定有效、可行的主机防护策略。 需求描述 > 网关服务器ens3…

【计算机网络】TCP原理 | 可靠性机制分析(二)

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程、计算机网络的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; T…

Kettle Local引擎使用记录(一)(基于Kettle web版数据集成开源工具data-integration源码)

Kettle Web &#x1f4da;第一章 前言&#x1f4da;第二章 demo源码&#x1f4d7;pom.xml引入Kettle引擎核心文件&#x1f4d7;java源码&#x1f4d5; controller&#x1f4d5; service&#x1f4d5; 其它&#x1f4d5; maven settings.xml &#x1f4d7;测试&#x1f4d5; 测试…

C语言中关于函数递归的理解

递归的概念&#xff1a;如果一个对象部分包含它自己,或者利用自己定义自己,则称这个对象是递归的;如果 一个过程直接或间接调用自己,则称这个过程是一个递归过程。递归的主要思考方式在于&#xff1a;将大事化小 我们先看一个例子 题目&#xff1a;输入一个无符号数&#xff0…

蜗牛目标检测数据集VOC格式480张

蜗牛&#xff0c;一种缓慢而坚韧的软体动物&#xff0c;以其螺旋形的外壳和黏附力极强的黏液而为人所熟知。 蜗牛体型呈螺旋形&#xff0c;有一个硬壳保护其柔软的身体。壳的形状和纹理因种类而异&#xff0c;有的光滑如玻璃&#xff0c;有的则布满细纹。蜗牛的头部有两对触角…

U-Boot学习(1):简介及命令行指令详解

Bootloader的主要任务是引导加载并运行应用程序&#xff0c;对于MCU中的BootLoader&#xff0c;我之前写过一篇详细的文章单片机中BootLoader的严谨实现详解介绍它实现的整体流程。对于Linux来说&#xff0c;在运行Linux内核之前也需要BootLoader进行引导&#xff0c;这个BootL…

Amazing OpenAI API:把非 OpenAI 模型都按 OpenAI API 调用

分享一个有趣的小工具&#xff0c;10MB 身材的小工具&#xff0c;能够将各种不同的模型 API 转换为开箱即用的 OpenAI API 格式。 让许多依赖 OpenAI API 的软件能够借助开发者能够接触到的&#xff0c;非 OpenAI 的 API 私有部署和使用起来。 写在前面 这个小工具软件写于两…

面试宝典进阶之redis缓存面试题

R1、【初级】Redis常用的数据类型有哪些&#xff1f; &#xff08;1&#xff09;String&#xff08;字符串&#xff09; &#xff08;2&#xff09;Hash&#xff08;哈希&#xff09; &#xff08;3&#xff09;List&#xff08;列表&#xff09; &#xff08;4&#xff09;Se…

zookeeper 与eureka区别

CAP定理 在分布式系统的发展中&#xff0c;影响最大的莫过于CAP定理了&#xff0c;是分布式系统发展的理论基石。 2000年&#xff0c;加州大学的计算机科学家 Eric Brewer提出了CAP猜想 2002 年&#xff0c;麻省理工学院的 Seth Gilbert 和 Nancy Lynch 从理论上证明了 CAP 猜…

深入理解 Hadoop (五)YARN核心工作机制浅析

概述 YARN 的核心设计理念是 服务化&#xff08;Service&#xff09; 和 事件驱动&#xff08;Event EventHandler&#xff09;。服务化 和 事件驱动 软件设计思想的引入&#xff0c;使得 YARN 具有低耦合、高内聚的特点&#xff0c;各个模块只需完成各自功能&#xff0c;而模…

静态关键字:static

static的作用 static是静态的意思&#xff0c;可以修饰成员变量和成员方法。 static修饰成员变量表示该成员变量只在内存中只存储一份&#xff0c;可以被共享访问、修改。 成员变量 分为2类 静态成员变量&#xff08;有static修饰&#xff0c;属于类&#xff0c;内存中加载…