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

Java 面试题解析:CountdownLatch、线程池、CAS、synchronized、Lock、多态等关键概念

在 Java 面试中,除了基础的语法知识外,面试官还会考察一些更深入的多线程编程和并发控制等高级话题。本文将详细解答一些常见的 Java 面试题,包括 CountDownLatch线程池的 submitexecute 方法Java 多态的实现原理CASsynchronizedLock 等技术概念,并提供代码示例加以解释。​编辑


1. CountDownLatch

CountDownLatch 是一个并发工具类,它允许一个或多个线程等待直到其他线程的操作完成。它的核心概念是通过一个计数器来控制线程的等待和释放。线程在 CountDownLatch 中调用 await() 方法等待,直到计数器达到零时才会被释放。计数器通过调用 countDown() 方法递减。​编辑

使用场景

  • 等待多个线程完成某项任务后,主线程才能继续执行。
  • 例如,在测试时等待多个线程完成工作再进行下一步操作。

示例

java 复制代码
import java.util.concurrent.CountDownLatch;

public class TestCountDownLatch {  
    public static void main(String[] args) throws InterruptedException {  
        int threadCount = 3;  
        CountDownLatch latch = new CountDownLatch(threadCount);

        Runnable task = () -> {  
            try {  
                Thread.sleep(1000);  
                System.out.println(Thread.currentThread().getName() + " done!");  
            } catch (InterruptedException e) {  
                Thread.currentThread().interrupt();  
            } finally {  
                latch.countDown(); // 计数器减1  
            }  
        };

        for (int i = 0; i < threadCount; i++) {  
            new Thread(task).start();  
        }

        latch.await(); // 主线程等待,直到计数器为0  
        System.out.println("All threads are done!");  
    }  
}  

输出

bash 复制代码
Thread-0 done!  
Thread-1 done!  
Thread-2 done!  
All threads are done!  

2. submit/execute ​编辑

在 Java 中,submit()execute() 都是线程池(ExecutorService)的常用方法,用于提交任务给线程池执行。它们之间的主要区别在于返回值和任务处理方式。

  • execute(Runnable) :用于提交一个 Runnable 类型的任务,不会返回任务的执行结果。任务执行时,如果发生异常,异常会被吞掉。编辑
  • submit(Runnable) :用于提交一个 Runnable 类型的任务,会返回一个 Future 对象,可以通过 Future 对象获取任务的执行结果或异常。

区别总结

  • execute 没有返回值,适合处理那些不关心任务执行结果的场景。
  • submit 返回 Future 对象,可以用于获取任务的执行状态、结果以及异常。

示例

java 复制代码
import java.util.concurrent.*;

public class TestSubmitExecute {  
    public static void main(String[] args) throws InterruptedException, ExecutionException {  
        ExecutorService executor = Executors.newFixedThreadPool(2);

        Runnable task1 = () -> System.out.println("Task1 executed");  
        Callable<String> task2 = () -> {  
            Thread.sleep(1000);  
            return "Task2 result";  
        };

        executor.execute(task1); // 不返回结果

        Future<String> future = executor.submit(task2); // 返回 Future  
        System.out.println(future.get()); // 输出 "Task2 result"

        executor.shutdown();  
    }  
}  

3. Java 多态实现原理

Java 中的多态(Polymorphism)是指同一个方法调用,可以根据对象的不同而表现出不同的行为。Java 实现多态的原理主要通过 方法重写方法动态绑定 来实现。

  • 方法重写:子类重新定义父类的方法。
  • 方法动态绑定:在运行时,根据对象的实际类型来决定调用哪个方法。

多态的实现原理

  • 方法调用时的动态绑定:Java 使用虚拟机(JVM)中的方法调用机制,方法的调用由编译时决定调用哪一个类的版本,但是实际方法的调用是在运行时动态绑定的。

示例

java 复制代码
class Animal {  
    public void sound() {  
        System.out.println("Animal makes sound");  
    }  
}

class Dog extends Animal {  
    @Override  
    public void sound() {  
        System.out.println("Dog barks");  
    }  
}

public class TestPolymorphism {  
    public static void main(String[] args) {  
        Animal animal = new Dog(); // 多态:父类引用指向子类对象  
        animal.sound(); // 输出 "Dog barks"  
    }  
}  

总结:Java 通过继承和方法重写实现多态,方法调用由 JVM 在运行时根据对象类型决定,称为动态绑定。


4. 线程池

线程池是为了避免频繁创建和销毁线程的开销,它通过复用线程来提高性能。Java 提供了 Executor 框架来管理线程池,常用的线程池有:

  • FixedThreadPool:线程池大小固定。
  • CachedThreadPool:线程池大小可以根据需要调整。
  • SingleThreadExecutor:单线程执行任务。
  • ScheduledThreadPool:可以定时执行任务。

线程池的常见方法有 submitexecute

示例

java 复制代码
import java.util.concurrent.*;

public class TestThreadPool {  
    public static void main(String[] args) {  
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        Runnable task = () -> System.out.println(Thread.currentThread().getName() + " is executing task");

        for (int i = 0; i < 5; i++) {  
            executorService.submit(task); // 提交任务  
        }

        executorService.shutdown(); // 关闭线程池  
    }  
}  

总结:线程池通过复用线程来提高性能,避免了频繁创建销毁线程的开销。


5. CAS(Compare-And-Swap)

CAS(比较并交换)是一种无锁的并发控制技术,通常用来实现原子操作。它通过原子地比较某个内存位置的值和预期值,如果两者相等,则将该内存位置的值更新为新值。

CAS 的优点是避免了加锁机制带来的性能问题,但也存在"ABA 问题",即值从 A 变为 B 再变回 A,CAS 无法检测这种变化。

示例

java 复制代码
import java.util.concurrent.atomic.AtomicInteger;

public class TestCAS {  
    private static AtomicInteger counter = new AtomicInteger(0);

    public static void main(String[] args) {  
        // 使用 CAS 自增  
        System.out.println("Counter: " + counter.getAndIncrement()); // 输出 0  
        System.out.println("Counter: " + counter.get()); // 输出 1  
    }  
}  

总结:CAS 是一种高效的并发控制技术,能够在不加锁的情况下实现原子操作,但需要注意一些细节问题,如 ABA 问题。


6. synchronized

synchronized 是 Java 提供的一种同步机制,用于解决多线程并发访问共享资源时的线程安全问题。它可以修饰方法或代码块,保证同一时刻只有一个线程能够执行被修饰的代码。

原理

  • 对象锁:每个对象都有一个锁,可以通过 synchronized 修饰方法来获取锁。
  • 类锁:如果 synchronized 修饰的是静态方法,则是类级别的锁。

示例

java 复制代码
public class TestSynchronized {  
    private int counter = 0;

    public synchronized void increment() {  
        counter++;  
    }

    public synchronized int getCounter() {  
        return counter;  
    }

    public static void main(String[] args) throws InterruptedException {  
        TestSynchronized test = new TestSynchronized();

        Runnable task = () -> {  
            for (int i = 0; i < 1000; i++) {  
                test.increment();  
            }  
        };

        Thread t1 = new Thread(task);  
        Thread t2 = new Thread(task);  
        t1.start();  
        t2.start();  
        t1.join();  
        t2.join();

        System.out.println("Counter: " + test.getCounter()); // 输出 2000  
    }  
}  

总结synchronized 是 Java 内置的同步机制,通过锁来保证线程安全。


7. Lock

Lock 是 Java 并发包中的接口,它提供了比 synchronized 更灵活的锁机制。Lock 可以更精确地控制锁的获取和释放,支持公平锁、重入锁等特性。

常用的实现类是 ReentrantLock

示例

java 复制代码
import java.util.concurrent.locks.Lock;  
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {  
    private int counter = 0;  
    private Lock lock = new

​
相关推荐
Yeats_Liao43 分钟前
时序数据库系列(二):InfluxDB安装配置从零搭建
数据库·后端·时序数据库
Yeats_Liao43 分钟前
时序数据库系列(一):InfluxDB入门指南核心概念详解
数据库·后端·时序数据库·db
蓝-萧1 小时前
springboot系列--自动配置原理
java·后端
bobogift2 小时前
【玩转全栈】----Django基本配置和介绍
java·后端
007php0072 小时前
某游戏互联网大厂Java面试深度解析:Java基础与性能优化(一)
java·数据库·面试·职场和发展·性能优化·golang·php
倚栏听风雨2 小时前
Async-Profiler 框架简介
后端
qianbailiulimeng2 小时前
2019阿里java面试题(一)
java·后端
码事漫谈2 小时前
虚函数指针与虚函数表:C++多态的实现奥秘
后端
Moment2 小时前
Cursor 2.0 支持模型并发,我用国产 RWKV 模型实现了一模一样的效果 🤩🤩🤩
前端·后端·openai
码事漫谈2 小时前
写博客实用工具!5分钟使用ShareX实现步骤批量截图
后端