面试真实经历某商银行大厂Java问题和答案总结(五)

作者:360_go_php日期:2025/10/15

Java 面试常见问题解析​编辑

Java 中的多线程和类加载机制是开发中非常重要的部分。在面试过程中,涉及线程管理和 JVM 的相关问题经常出现。本文将探讨一些 Java 面试中的常见问题,并为每个问题提供详细的解答。

​编辑---

1. 线程的同步方法

线程的同步方法是指通过某些机制来控制多线程环境中多个线程对共享资源的访问,以防止数据冲突。以下是几种常见的同步方法:

  1. synchronized 关键字
    synchronized 关键字可以用来修饰方法或代码块,确保同一时刻只有一个线程能够访问被修饰的方法或代码块。
    - 同步方法:方法声明时使用 synchronized 关键字,这样该方法的代码会被同步执行。

java    public synchronized void syncMethod() {        // 线程安全的代码    }     2. Lock 接口(ReentrantLock)
ReentrantLock 是 Java 提供的显式锁,它比 synchronized 更加灵活,可以实现更细粒度的同步控制,且提供了尝试锁和超时锁等特性。​编辑

java    Lock lock = new ReentrantLock();    try {        lock.lock();        // 线程安全的代码    } finally {        lock.unlock();    }     3. 原子变量(Atomic 类)
Atomic 类(如 AtomicInteger)提供了原子操作的方法,可以确保对基本类型的原子性操作,避免了多线程竞争条件的问题。

java    AtomicInteger counter = new AtomicInteger(0);    counter.incrementAndGet();  // 原子性自增    


2. 几种方法创建线程

在 Java 中,有多种方式可以创建和启动线程,以下是最常见的三种方式:

  1. 继承 Thread 类
    创建一个继承 Thread 类的子类,重写 run 方法,并调用 start 启动线程。

java    class MyThread extends Thread {        @Override        public void run() {            System.out.println("Thread is running");        }    }        MyThread thread = new MyThread();    thread.start();     2. 实现 Runnable 接口
实现 Runnable 接口并将其传递给 Thread 类的构造方法,适用于多个线程共享同一个 Runnable 实现的情况。

java    class MyRunnable implements Runnable {        @Override        public void run() {            System.out.println("Runnable thread is running");        }    }        Thread thread = new Thread(new MyRunnable());    thread.start();     3. 使用线程池(ExecutorService)
使用 ExecutorService 可以创建一个线程池来管理线程的创建与销毁,避免了手动管理线程的麻烦。

java    ExecutorService executorService = Executors.newFixedThreadPool(10);    executorService.submit(() -> System.out.println("Thread pool task"));    executorService.shutdown();    


3. 线程的几种状态

Java 线程在生命周期中会经历不同的状态,以下是线程的几种常见状态:

  1. New(新建状态)
    线程创建后尚未调用 start() 方法时处于 New 状态。

java    Thread t = new Thread();    System.out.println(t.getState());  // 输出:NEW     2. Runnable(可运行状态)
线程调用了 start() 方法后进入 Runnable 状态,此时线程在 JVM 中排队等待 CPU 时间片来执行。 3. Blocked(阻塞状态)
当线程因为等待获取某个锁而无法继续执行时,它进入 Blocked 状态。 4. Waiting(等待状态)
线程通过调用 wait()join()LockSupport.park() 等方法进入 Waiting 状态,直到被唤醒。 5. Timed Waiting(定时等待状态)
线程处于 sleep()join(time)wait(time) 等方法指定的时间范围内时,会进入定时等待状态。 6. Terminated(终止状态)
线程的 run() 方法执行完毕后或者被异常终止时,线程进入 Terminated 状态。


4. 线程如何从运行到挂起

线程在运行时,可以通过某些机制挂起,通常是因为等待某些条件或资源:

  • 通过调用 Thread.sleep()
    线程调用 sleep 方法会使其进入 Timed Waiting 状态,经过指定时间后自动恢复到 Runnable 状态。

java   try {       Thread.sleep(1000);  // 线程挂起1秒钟   } catch (InterruptedException e) {       e.printStackTrace();   }  

  • 通过调用 Object.wait()
    线程通过 wait() 方法进入 Waiting 状态,直到其他线程调用同一个对象的 notify()notifyAll() 方法来唤醒它。

java   synchronized (lock) {       lock.wait();  // 当前线程进入等待状态   }  


5. 动态代理

动态代理是指在运行时动态生成一个代理对象,并指定其代理行为。Java 中的动态代理有两种方式:

  1. 基于接口的动态代理(通过 Proxy 类):
    使用 Java 提供的 Proxy 类和 InvocationHandler 接口来实现动态代理。通常用于为接口创建代理。

```java
public interface Hello {
void sayHello();
}

public class HelloImpl implements Hello {
public void sayHello() {
System.out.println("Hello, World!");
}
}

public class HelloProxy implements InvocationHandler {
private Object target;

public HelloProxy(Object target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method call");
return method.invoke(target, args);
}
}

public class ProxyDemo {
public static void main(String[] args) {
Hello hello = new HelloImpl();
Hello proxy = (Hello) Proxy.newProxyInstance(
hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(),
new HelloProxy(hello)
);
proxy.sayHello();
}
}
```

  1. 基于类的动态代理(通过 CGLIB):
    使用第三方库 CGLIB 实现类的动态代理,它不要求目标类实现接口。

java    Enhancer enhancer = new Enhancer();    enhancer.setSuperclass(HelloImpl.class);    enhancer.setCallback(new MethodInterceptor() {        @Override        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {            System.out.println("Before method call");            return proxy.invokeSuper(obj, args);        }    });    HelloImpl hello = (HelloImpl) enhancer.create();    hello.sayHello();    


6. Java 类加载如何进行

Java 的类加载是由 ClassLoader 完成的,Java 采用了双亲委派模型来加载类。其基本流程如下:

  1. 加载:通过类加载器将 .class 文件加载到 JVM 中。
  2. 连接
    - 验证:确保类的字节码符合 Java 语言规范。
    - 准备:为类的静态变量分配内存并初始化默认值。
    - 解析:将符号引用转换为直接引用。
  3. 初始化:执行类的静态初始化块和静态变量初始化。

7. Java 类加载的几种状态

Java 类加载有以下几种状态:

  1. 加载(Loading):类文件从磁盘加载到内存中。
  2. 链接(Linking):包括验证、准备和解析过程。
  3. 初始化(Initialization):执行静态初始化块,初始化类的静态变量。

8. Java JVM 中 GC 如何进行线程是否需要回收的判断

**垃圾回收(GC)**是 Java 的 JVM 负责的自动内存管理机制。GC 会根据对象的可达性来判断是否需要回收:

  1. 可达性分析:通过从根对象(如栈、方法区等)开始遍历,检查对象是否可达。如果一个对象不可达,则说明该对象可以被回收。
  2. 引用计数法:通过记录对象的引用次数来判断其是否可回收。当引用次数为 0 时,对象可以被回收。​编辑

JVM 中的垃圾回收算法通常有 标记-清除复制算法分代收集 等。


通过掌握这些 Java 多线程、类加载、代理和 GC 的基础概念.


面试真实经历某商银行大厂Java问题和答案总结(五)》 是转载文章,点击查看原文


相关推荐


Agent 开发设计模式(Agentic Design Patterns )第 2 章:路由模式
shiter2025/10/13

文章大纲 路由模式概览 路由的基本流程 路由机制的类型 路由的部署节点 框架支持 实际应用与用例 1. 人机交互系统 2. 自动化数据处理流水线 3. 多工具/多代理协同系统 4. 系统价值总结 动手代码示例(LangChain) 动手代码示例(Google ADK) 核心总结与最佳实践 什么是


LLM模型与ML算法之间的关系
Juchecar2025/10/12

三要素 机器学习的是算法、算力和数据,LLM的是模型、算力和数据。 ——约去同类项,那么问题来了:算法和模型之间是什么关系? 这是一个非常敏锐且深刻的观察。您提出的论述没有根本性的逻辑矛盾,但揭示了在不同技术范式下,对核心要素的表述侧重点发生了转移。 我们可以从两个层面来理解这个问题: “算法”和“模型”在概念上是相通的,但存在层次和侧重点的差异。 LLM是机器学习的一个子集(尽管是极其庞大和重要的一个),其要素的表述反映了其技术范式的特殊性。 下面我们来详细拆解。 1. “算法”与“模型”


【腾讯拥抱开源】Youtu-Embedding:基于CoDiEmb的一个协作而独特的框架,用于信息检索与语义文本相似性中的统一表征学习
吴脑的键客2025/10/10

🎯 简介 Youtu-Embedding 是由腾讯优图实验室开发的尖端通用文本嵌入模型。该模型在信息检索(IR)、语义文本相似度(STS)、聚类、重排序和分类等各类自然语言处理任务中均展现出卓越性能。 顶尖性能表现:截至2025年9月,在权威的CMTEB(中文大规模文本嵌入基准)评测中以77.46分位列榜首,彰显其强大稳健的文本表征能力。 创新训练框架:采用协同判别式微调框架,通过统一数据格式、任务差异化损失函数及动态单任务采样机制,有效解决多任务学习中的"负迁移"问题。 注:您可


sensitive-word:一个简单易用的敏感词过滤框架
勇哥Java实战2025/10/9

这篇文章,分享一个开源项目:sensitive-word 。 Github 地址:github.com/houbb/sensi… sensitive-word 是一个功能强大的 Java 敏感词过滤框架,它不仅提供了基础的敏感词检测功能,还支持单词标签分类分级、繁简体互换、全角半角互换、汉字转拼音、模糊搜索等高级特性。 它的核心特性如下: 🚀 高性能: 基于 DFA 算法,匹配效率极高 🏷️ 标签分类: 支持敏感词分类分级管理 🔄 字符处理: 支持繁简体、全角半角互换 🎯 模糊搜


Less resolver error:‘~antd/es/style/themes/index.less‘ wasn‘t found.
北阳AI知行录2025/10/7

记录一次使用Ant Design Pro框架时出现的bug 这是我最开始的package.json版本,然后执行npm run build(max build) 打包时会报上面的错误 { "name": "ant-design-pro", "version": "6.0.0", "private": true, "description": "An out-of-box UI solution for enterprise applications", "repo


【微服务】SpringBoot + Docker 实现微服务容器多节点负载均衡详解
小码农叔叔2025/10/6

目录 一、前言 二、前置准备 2.1 基本环境 2.2 准备一个springboot工程 2.2.1 准备几个测试接口 2.3 准备Dockerfile文件 2.4 打包上传到服务器 三、制作微服务镜像与运行服务镜像 3.1 拷贝Dockerfile文件到服务器 3.2 制作服务镜像 3.3 启动镜像服务 3.4 访问一下服务接口 四、配置负载均衡 4.1 源码包方式安装nginx 4.1.1 下载nginx安装包 4.1.2 解压安装包 4.1.3 进入解


为什么 Vue 组件中的 data 必须是一个函数?(含 Vue2/3 对比)
excel2025/10/5

在 Vue 面试或日常开发中,经常会被问到这样一个问题:为什么组件中的 data 必须是一个函数,而根实例的 data 可以是对象或函数? 本文将从 实例与组件的区别、数据污染问题、源码实现原理,以及 Vue2/3 的差异 四个角度进行深入分析。 一、实例与组件定义 data 的区别 在 Vue 根实例 中,data 属性既可以是对象,也可以是函数: // 对象格式 const app = new Vue({ el: "#app", data: { foo: "foo" }


VUE3+element plus 实现表格行合并
rggrgerj2025/10/3

基础实现方法 通过给el-table传入span-method方法可以实现合并行或列,该方法的参数包含当前行row、当前列column、当前行号rowIndex和当前列号columnIndex四个属性15。该方法可以返回包含rowspan和colspan的数组或对象,例如: javascriptCopy Code const spanMethod = ({ row, column, rowIndex, columnIndex }) => { if (columnIndex === 0


数模之路获奖总结——数据分析交流(R语言)
统计学小王子2025/10/2

目录 0、引言1、主要参赛类型2、涉及领域汇总2.1、 数据科学与人工智能前沿应用2.2、 社会经济与公共政策研究2.3、 医疗卫生与生物制药2.4、 能源环境与可持续发展2.5、工程技术与运筹优化2.6、 计算与通信基础设施2.7、 其他特色领域2.8、总结 3、主要比赛获奖总结4、写在最后的话 0、引言 自2018年1月起,开始跟着学校由徐老师负责的培训老师团队了解、入门和学习数学建模并通过选拔拿到第一张国赛入场券。时至今日(2025年9月27),已经关注和参加了大大小小的建模


阿里开源 Java 诊断神器Arthas
讓丄帝愛伱2025/10/2

支持 JDK6+,零侵入,通过 Attach 机制连接 JVM,无需重启服务即可定位问题。 CLI 支持 Tab 自动补全,并提供 Web Console。 Github | 官网文档 一、核心价值 线上问题快速定位:CPU 飙升、内存泄漏、线程阻塞动态反编译验证代码:jad 命令方法级性能分析:耗时、调用频次、异常统计热更新/日志修改:无需重启即可修改代码或日志格式 优势: 零侵入全功能 CLI多环境支持(Linux/Mac/Windows + JDK6+) 二、安装与

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0