面试真实经历某商银行大厂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

​
相关推荐
Postkarte不想说话3 小时前
FreeBSD配置Jails
后端
但求无bug3 小时前
Java中计算两个日期的相差时间
后端
小傅哥3 小时前
新项目完结,Ai Agent 智能体、拖拉拽编排!
前端·后端
廖广杰3 小时前
java虚拟机-如何通过GC日志判断晋升失败(Promotion Failed)
后端
自由的疯3 小时前
优雅的代码java
java·后端·面试
gensue3 小时前
【征文计划】深度解析Rokid UXR 2.0 SDK:Unity开发者的空间计算开发利器
后端
kingg3 小时前
【征文计划】基于 Rokid JSAR 的 2D 粒子画廊实现:从技术概述到核心代码解析
github
.NET修仙日记3 小时前
2025年ASP.NETMVC面试题库全解析
面试·职场和发展·c#·asp.net·mvc·面试题·asp.net mvc
绝无仅有3 小时前
面试真实经历某商银行大厂Java问题和答案总结(二)
后端·面试·github