八股相关
一、具体问题
(Java 语言)1. wait 和 sleep 方法的区别?
(Kafka)2. Kafka 有哪些优点/缺点?
(JUC)3. 线程池的运行流程是怎么样的?
(JUC)4. 线程池如果设置过大了,会怎么样?
(JUC)5. 线程池要是没有关闭,那么一直运行下去,他接下来会一直运行吗,还是自动关闭?
(JUC)6. 你自己如何根据业务调整线程池的大小的,判断依据在哪?
(Redis)7. 如何保障本地缓存和 redis 实现数据一致性?
(设计模式)8. 什么是享元模式?
(JUC)9. 什么是 AQS?它有什么作用?如何使用?
(JUC)10. 可重入锁的底层加锁和释放锁是怎么样的呢?
(Spring)11. Spring Cloud 与 Spring Boot 区别是什么?
二、参考答案
(Java 语言)1. wait 和 sleep 方法的区别?
wait 和 sleep 方法区别体现在:
-
wait 方法属于 Object 类的方法。在调用 wait 方法前,需要获取内部的监视器锁。因此,需要在同步代码块中使用;sleep 方法属于 Thread 类的方法。可以在任何地方使用。
-
wait 方法在调用时,会释放持有的锁;而 sleep 方法在调用时,不会释放持有的锁。
-
wait 方法在调用时,会一直等待直到被唤醒;而 sleep 方法在调用时,只会暂停一段时间。
(Kafka)2. Kafka 有哪些优点/缺点?
Kafka 优点包括:
- 高性能:Kafka 提供了高吞吐量和低延时的消息传递能力,可以支持大规模的数据处理。
- 可扩展:Kafka 是一个分布式系统,可以扩展到多结点。
- 可靠性:Kafka 提供多种备份机制,可以保证消息传递到可靠性。
Kafka 缺点包括:
- 处理存在延时。由于 Kafka 批量处理消息,在高峰期可能会存在延时情况。
- 仅支持统一分区内的消息有序,无法实现全局消息有序。
- Kafka 依赖于 Zookeeper 来管理集群的状态和元数据。当 Zookeeper 配置出错时,Kafka 受到很大的影响。
(JUC)3. 线程池的运行流程是怎么样的?
线程池的运行流程包括:
- 第一,创建线程池,初始化线程池中空闲线程的数量。
- 第二,提交任务,通过程序分配任务到线程池中。
- 第三,执行任务,由线程池分配空闲的线程来执行任务。
- 第四,结束任务,当线程执行完任务后,会回归到线程池中。
- 最后,销毁线程池,当程序不再使用线程池时,可以调用销毁方法来销毁线程池。
下面指的线程池是 ThreadPoolExecutor 类。
提交任务: 调用线程池的 execute() 方法。
销毁方法: 调用线程池的 shutdown() 方法。
(JUC)4. 线程池如果设置过大了,会怎么样?
线程池设置过大,可能会出现多种问题,例如:
- 占用内存资源。当线程池设置过大,但是执行任务的线程很少时,会造成空闲线程过大,存在资源浪费。
- 线程切换花销。当线程池设置过大,会造成线程切换的频率相较而言更加频繁,造成花销增大。
- 导致系统不稳定。当线程池设置过大,线程数量增多后,可能会因为线程之间的资源竞争,导致死锁。
(JUC)5. 线程池要是没有关闭,那么一直运行下去,他接下来会一直运行吗,还是自动关闭?
线程池要是没有被关闭,这个线程池对象在方法调用结束后,JVM 会回收它占用的内存资源。
但是,线程池中创建的线程将一直存在,除非在线程池对象被回收前调用它的销毁方法 shutdown
。
或者是等待 JVM 被关闭后。
(JUC)6. 你自己如何根据业务调整线程池的大小的,判断依据在哪?
我的业务中没有使用到线程池,但是使用了到线程池中的本地线程类 ThreadLocal
。
使用这个类的目的是用于创建线程的副本,主要是用于保存用户的登录信息,方便用户登录状态的查询。
并且,在多线程环境下,业务方法访问到的是所处线程下的用户信息,比较方便。
(Redis)7. 如何保障本地缓存和 redis 实现数据一致性?
本地缓存和 Redis 实现数据的一致性,可以通过中心化和去中心化方式来保障。
- 对于中心化方式,就是将缓存管理的职责交给中心节点负责,同时随时进行数据的同步。
- 但是它的缺点是,当中心节点故障时,导致整个系统瘫痪。
- 对于去中心化方式,每个节点都可以缓存相同的数据,然后通过通信协议来同步缓存数据。
用于同步的通信协议有哪些?
包括 Gossip 协议、P2P 协议、Zookeeper 协议等等。
类似问题:如何保障 Redis 缓存和数据库中数据一致性?
数据一致性的保障可以分为「读、写操作」进行分析:
- 对于读操作
- 如果数据在缓存中存在,则从缓存直接读出。
- 如果数据在缓存中不存在,先从数据库中读出,再缓存在 Redis 中。
- 对于写数据
- 如果缓存中不存在,和读的情况一致。
- 如果缓存中存在,先写入 Redis 中,同时标记为脏数据。当这些数据要被移除时,才写回数据库。
(设计模式)8. 什么是享元模式?
享元模式是设计模式的一种,它的作用是减少创建对象的数据,来提高性能的内存的利用率。
这个模式的核心是 对象的共享,而不是每一次需要一个新对象时都创建一个新的实例。
(JUC)9. 什么是 AQS?它有什么作用?如何使用?
AQS(Abstract Queued Synchronizer,抽象队列同步器)是 JUC 包下的一个组件,它主要用于线程之间的同步。
它底层的思想是使用一个先进先出的队列来管理线程之间的资源竞争。
所有等待访问共享资源的线程都将被加入到这个队列中,并通过 CAS 操作获取等待资源的访问权。
**可重入锁(ReentrantLock)**底层加锁和释放锁主要是通过 AQS 实现的。
复习:什么是 CAS?
CAS 是一种 乐观锁机制,它使用原子操作对某个内存位置的值进行比较和修改。
当这个内存位置的值与预期值相等时,才会将该位置的值更新为新值,否则操作失败。
(JUC)10. 可重入锁的底层加锁和释放锁是怎么样的呢?
可重入锁的底层维护了一个 AQS 内部对象。
当可重入锁调用加锁 lock 方法时,会调用底层 AQS 的 tryAquire 方法。这个方法会读取同步器的状态。
- 如果同步器的状态为 0,表示当前线程可以获取锁,然后将同步器状态设置为 1。
- 如果同步器的状态不为 0,表示当前线程已经持有锁,同时增加“加锁”的这个状态。
当可重入锁调用释放锁 unlock 方法时,会调用底层 AQS 的 tryRelease 方法。
这个方法的实现过程与上锁的方法,在逻辑上是一个逆过程。同时,AQS 上锁和释放锁过程中都使用了 CAS 锁。
(Spring)11. Spring Cloud 与 Spring Boot 区别是什么?
Spring Boot 是一个用于构建基于 Spring 的应用程序的快速开发框架,使得开发人员可以快速搭建应用程序。
Spring Cloud 则是一组分布式系统开发框架,它基于 Spring Boot,提供了许多分布式系统所需的功能。
总的来说,Spring Boot 主要用于构建独立的 Spring 应用程序,而 Spring Cloud 则用于构建分布式系统。
它在 Spring Boot 的基础上提供了分布式系统所需的各种功能和工具。
三、今日感悟
今天八股主要看了 JUC 相关,之前一直疑惑什么是 AQS,原来本质上就是一个用于同步的工具,而且它就被可重入锁所使用。还顺带看了下可重入锁的源码,还挺有意思的。就酱!