面试总结-Java

简单介绍双亲委派机制

A:双亲委派机制是Java中的一种类加载机制。当一个类加载器收到类加载请求时,它会将请求委派给其父类加载器去尝试加载,只有当父类加载器无法完成加载时,子类加载器才会尝试自己去加载。这种机制的目的是保证类的加载是有序的,避免重复加载同一个类,并保护程序的安全,防止核心API被随意篡改。

Java线程池的底层原理是什么?

Java线程池的底层原理主要基于ThreadPoolExecutor类,该类提供了一个灵活且可配置的线程池实现。以下是Java线程池的主要原理:

1. **核心组件:**
   - `ThreadPoolExecutor` 是线程池的核心组件,它负责管理和执行线程池中的任务。
   - 线程池包含一些核心参数,如核心线程数、最大线程数、线程空闲时间等。

2. **任务队列:**
   - 线程池使用一个任务队列来保存等待执行的任务。任务队列可以是有界队列或无界队列,常见的有 `LinkedBlockingQueue` 和 `ArrayBlockingQueue`。

3. **线程工厂:**
   - 线程池使用线程工厂来创建新的线程。默认的线程工厂是 `Executors.defaultThreadFactory()`。

4. **拒绝策略:**
   - 当任务无法被接收时,线程池采用拒绝策略来处理。常见的拒绝策略有:
     - `AbortPolicy`:抛出 `RejectedExecutionException`。
     - `CallerRunsPolicy`:由调用线程执行任务。
     - `DiscardPolicy`:直接丢弃无法处理的任务。
     - `DiscardOldestPolicy`:丢弃队列头部的任务,尝试再次提交当前任务。

5. **线程执行流程:**
   - 当有任务提交到线程池时,线程池首先检查核心线程是否已满,如果没有满,则创建一个新的核心线程来执行任务。
   - 如果核心线程已满,任务将被放入任务队列中。
   - 如果任务队列已满,而线程数未达到最大线程数,则创建新的非核心线程来执行任务。
   - 如果任务队列已满且线程数达到最大线程数,根据拒绝策略处理任务。

6. **线程池的生命周期管理:**
   - 线程池有其生命周期,可以通过 `shutdown()` 方法关闭线程池。调用 `shutdown()` 后,线程池将拒绝新任务,并尝试终止当前正在执行的任务。

7. **饱和策略:**
   - 线程池的饱和策略是在任务无法被放入队列时所采取的策略。可以通过 `setRejectedExecutionHandler()` 方法来设置饱和策略。

总体来说,Java线程池的底层原理是通过`ThreadPoolExecutor`类来管理线程,利用任务队列、线程工厂、拒绝策略等组件来协调线程的创建和任务的执行,从而提高系统的性能和稳定性。

Sychonized 与 Lock的区别

`Synchronized` 和 `Lock` 都可以用于实现多线程同步,但在实现上有一些区别:

1. **使用方式**:
   - `synchronized` 是 Java 语言的关键字,可以直接应用于方法或代码块中。
   - `Lock` 是 Java 中的一个接口,需要通过 `ReentrantLock` 等实现类来创建锁对象,并且需要手动获取锁和释放锁。

2. **灵活性**:
   - `synchronized` 在锁的获取和释放上较为简单,但是缺乏灵活性,例如无法中断一个正在等待获取锁的线程,也无法尝试获取锁而不阻塞。
   - `Lock` 接口提供了更多灵活性的方法,例如 `tryLock()` 可以尝试获取锁并立即返回,`lockInterruptibly()` 可以响应中断。

3. **锁的获取**:
   - `synchronized` 在获取锁时是隐式的,当一个线程进入 `synchronized` 方法或代码块时,会自动获取锁,并在方法或代码块执行完毕后释放锁。
   - `Lock` 需要显式地调用 `lock()` 方法来获取锁,并在使用完锁之后调用 `unlock()` 方法释放锁。

4. **性能**:
   - 在 JDK 1.6 之前,`synchronized` 的性能较差,但在 JDK 1.6 之后,对 `synchronized` 进行了很多优化,性能有了很大的提升。
   - `Lock` 的性能一般而言比 `synchronized` 略差,因为它需要手动获取和释放锁,并且有更多的代码处理。

综上所述,`synchronized` 是 Java 中最基本和最常用的同步方法,简单易用;而 `Lock` 提供了更多的功能和灵活性,适用于更复杂的多线程场景。

sychronied修饰普通方法和静态方法的区别?什么是可见性?

可见性(Visibility)指的是在多线程环境下,一个线程对共享变量的修改能否及时地被其他线程看到。在 Java 中,如果一个变量没有被 volatilesynchronized 或者 java.util.concurrent 库中的锁等保护起来,那么就可能存在可见性问题。也就是说,一个线程修改了变量的值,但是其他线程可能无法立即看到这个变化。这可能导致程序出现意料之外的行为,因为线程之间无法正确地协调共享数据的访问。

CAS无锁编程的原理

CAS(Compare and Swap)是一种无锁编程的技术,用于实现多线程环境下的原子操作。它的原理可以简单概括为:比较并交换。

CAS 操作包括三个操作数:内存位置(V)、期望的值(A)和新值(B)。操作执行的时候,只有当内存位置的值等于期望的值时,才会将该位置的值更新为新值,否则不做任何操作。整个操作是原子的,不会被其他线程中断。

CAS 操作通常包含以下步骤:

1. 读取内存位置 V 的值,记为 A。
2. 检查 V 的值是否等于 A,如果相等,则执行步骤 3;否则,说明其他线程已经修改了 V 的值,操作失败。
3. 将 V 的值更新为新值 B。

CAS 的优点在于它避免了使用锁带来的性能开销,因为它是基于硬件提供的原子操作指令(如 x86 架构的 `cmpxchg` 指令)实现的,不需要进入内核态,不会造成线程的阻塞。但是,CAS 也有一些缺点,最主要的是存在ABA问题,即在执行 CAS 操作过程中,内存位置的值可能被修改了多次,但最终又恢复原值,这样可能导致 CAS 操作误认为没有被修改过。为了解决ABA问题,可以使用版本号等方式来辅助 CAS 操作。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值