Java 开发岗及 java 架构师百度校招历年经典面试题汇总

简介: 以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。

以下是百度校招Java开发岗和Java架构师的部分面试题及答案:

Java开发岗

  • Hashmap如何变线程安全,每种方式的优缺点?
    • 使用Collections.synchronizedMap():优点是实现简单,直接调用工具方法即可。缺点是效率相对较低,因为其内部是通过 synchronized 关键字实现同步,整个Map的操作都被锁控制,并发度不高。
    • 使用ConcurrentHashMap:优点是性能高,采用分段锁机制,允许多个线程同时访问不同的分段,并发性能好。缺点是相比HashMap实现更复杂,占用内存可能稍多。
  • 服务器如何负载均衡,有哪些算法,哪个比较好?一致性哈希原理是什么,怎么避免DDOS攻击请求打到少数机器?
    • 负载均衡算法:常见的有轮询算法、加权轮询算法、随机算法、最少连接数算法等。轮询算法简单公平,但未考虑服务器性能差异;加权轮询可根据服务器性能分配请求,更合理;随机算法具有随机性;最少连接数算法将请求分配给连接数最少的服务器,能更好地利用服务器资源。
    • 一致性哈希原理:将服务器节点映射到一个0 - 2^32的哈希环上,请求根据其键值哈希后也映射到环上,然后按顺时针方向找到离它最近的服务器节点处理请求。
    • 避免DDOS攻击:可通过部署防火墙、设置访问频率限制、使用CDN(内容分发网络)等方式,CDN可将请求分散到多个节点,防火墙和访问频率限制能过滤掉异常高频请求,减少目标服务器压力。
  • Redis的持久化怎么做,aof和rdb有什么区别,各自优缺点是什么?
    • RDB:优点是生成的快照文件紧凑,占用空间小,恢复数据速度快。缺点是可能会丢失最后一次快照之后到故障发生期间的数据,且生成快照时可能会阻塞主线程。
    • AOF:优点是数据安全性高,能记录每一个写操作,最多只丢失一个命令的数据。缺点是文件体积较大,恢复数据时需要重放所有写命令,速度相对较慢,且可能存在日志文件过大需要定期重写的情况。

Java架构师

  • JMM(主内存、工作内存、happens - before)是什么?
    • JMM即Java内存模型,定义了线程和主内存之间的交互规则。主内存是所有线程共享的内存区域,存储了对象实例等数据。工作内存是每个线程私有的,线程对变量的操作先在工作内存中进行,然后再同步到主内存。happens - before是JMM中的一个重要概念,用于定义操作之间的先后顺序,保证内存可见性和有序性,若A happens - before B,则A操作的结果对B可见,且A的操作顺序排在B之前。
  • 有哪些无锁数据结构?无锁实现的原理是什么?
    • 无锁数据结构:常见的有ConcurrentHashMap(部分操作无锁)、乐观锁实现的容器等。
    • 原理:主要基于CAS(Compare - And - Swap)操作,它是一种原子操作,通过比较内存中的值和预期值,如果相等则进行更新,无需加锁就能实现多线程对数据的并发访问,提高了并发性能。
  • MySQL怎么优化table scan?
    • 添加合适索引:分析查询语句,对经常用于条件过滤、连接条件的列添加索引,但要避免过多索引导致更新性能下降。
    • 优化查询语句:尽量明确查询条件,避免使用SELECT *,只查询需要的列,减少数据扫描量。
    • 分区表:如果表数据量很大,可根据某些规则(如时间、地域等)将表分区,查询时只扫描相关分区,减少扫描范围。
    • 优化表结构:合理设计字段类型,避免使用过大的字段类型,减少数据存储量,从而降低扫描成本。

其他面试题答案如下:

  • 红黑树的插入时间复杂度:红黑树是一种自平衡的二叉查找树,插入一个新节点后,可能会破坏红黑树的性质,需通过旋转和重新着色来恢复平衡,插入的时间复杂度为O(logn)。
  • 解决哈希冲突的方式:常见的有链地址法(HashMap采用)、开放定址法(包括线性探测、二次探测等)、再哈希法、建立公共溢出区等。
  • G1什么时候引发Full GC:堆内存不足、晋升失败(新生代对象晋升到老年代时,老年代空间不足)、元空间不足等情况可能会引发G1的Full GC。
  • TCP握手挥手过程及其状态转换:三次握手过程为客户端发送SYN包进入SYN_SENT状态,服务器接收后回复SYN + ACK包进入SYN_RCVD状态,客户端再发送ACK包进入ESTABLISHED状态,服务器也进入ESTABLISHED状态。四次挥手过程为客户端发送FIN包进入FIN_WAIT_1状态,服务器接收后回复ACK包进入CLOSE_WAIT状态,客户端收到ACK后进入FIN_WAIT_2状态,服务器发送FIN包进入LAST_ACK状态,客户端接收FIN后回复ACK并进入TIME_WAIT状态,服务器收到ACK后进入CLOSED状态,客户端等待2MSL后也进入CLOSED状态。

百度校招Java开发岗历年经典面试题汇总(实操篇)

一、Java基础

1.1 JDK和JRE的区别

实操场景:验证JDK和JRE的安装与区别

# 检查JDK版本
java -version
javac -version

# 查看JDK安装路径
which java
which javac

# 验证JRE是否包含编译器
# 尝试在仅安装JRE的环境中执行javac命令,会提示"command not found"

1.2 ==和equals的区别

代码示例

public class EqualsDemo {
   
    public static void main(String[] args) {
   
        // 基本类型比较
        int a = 10;
        int b = 10;
        System.out.println("基本类型比较: " + (a == b)); // true

        // 引用类型比较
        String str1 = new String("hello");
        String str2 = new String("hello");
        System.out.println("引用地址比较: " + (str1 == str2)); // false
        System.out.println("值比较: " + str1.equals(str2)); // true

        // 字符串常量池比较
        String str3 = "world";
        String str4 = "world";
        System.out.println("常量池引用比较: " + (str3 == str4)); // true
    }
}

1.3 final的作用

代码示例

// 1. final类不能被继承
final class FinalClass {
   
    public void print() {
   
        System.out.println("Final Class");
    }
}

// 2. final方法不能被重写
class Parent {
   
    public final void finalMethod() {
   
        System.out.println("Final Method");
    }
}

class Child extends Parent {
   
    // 以下代码会编译错误,无法重写final方法
    // public void finalMethod() {}
}

// 3. final变量必须初始化且不可修改
class FinalVariableDemo {
   
    final int MAX_COUNT = 100;
    final String NAME;

    public FinalVariableDemo(String name) {
   
        this.NAME = name; // 必须在构造函数中初始化
    }

    public void test() {
   
        // MAX_COUNT = 200; // 编译错误,无法修改final变量
    }
}

1.4 String相关问题

实操场景:性能对比测试(String vs StringBuilder)

public class StringPerformanceTest {
   
    public static void main(String[] args) {
   
        int loopCount = 10000;

        // 使用String拼接
        long startTime = System.currentTimeMillis();
        String str = "";
        for (int i = 0; i < loopCount; i++) {
   
            str += i;
        }
        long endTime = System.currentTimeMillis();
        System.out.println("String拼接耗时: " + (endTime - startTime) + "ms");

        // 使用StringBuilder拼接
        startTime = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < loopCount; i++) {
   
            sb.append(i);
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuilder拼接耗时: " + (endTime - startTime) + "ms");
    }
}

1.5 抽象类与接口

代码示例:实现多继承特性

// 接口定义
interface Flyable {
   
    void fly();
}

interface Swimmable {
   
    void swim();
}

// 抽象类定义
abstract class Animal {
   
    abstract void eat();
}

// 实现类
class Duck extends Animal implements Flyable, Swimmable {
   
    @Override
    public void fly() {
   
        System.out.println("鸭子会飞");
    }

    @Override
    public void swim() {
   
        System.out.println("鸭子会游泳");
    }

    @Override
    void eat() {
   
        System.out.println("鸭子吃水草");
    }
}

1.6 Java中IO流

实操场景:文件复制工具实现

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class FileCopyDemo {
   
    public static void main(String[] args) {
   
        String sourceFile = "source.txt";
        String targetFile = "target.txt";

        // 1. 使用传统字节流
        try (InputStream is = new FileInputStream(sourceFile);
             OutputStream os = new FileOutputStream(targetFile)) {
   

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
   
                os.write(buffer, 0, bytesRead);
            }
            System.out.println("传统字节流复制完成");
        } catch (IOException e) {
   
            e.printStackTrace();
        }

        // 2. 使用NIO.2 Files工具类
        try {
   
            Path sourcePath = Paths.get(sourceFile);
            Path targetPath = Paths.get(targetFile);
            Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
            System.out.println("NIO.2复制完成");
        } catch (IOException e) {
   
            e.printStackTrace();
        }
    }
}

1.7 Files的常用方法

代码示例:文件操作工具类

import java.io.IOException;
import java.nio.file.*;
import java.util.List;

public class FileUtils {
   
    // 检查文件是否存在
    public static boolean checkFileExists(String filePath) {
   
        Path path = Paths.get(filePath);
        return Files.exists(path);
    }

    // 创建新文件
    public static void createFile(String filePath) throws IOException {
   
        Path path = Paths.get(filePath);
        Files.createFile(path);
    }

    // 创建目录
    public static void createDirectory(String dirPath) throws IOException {
   
        Path path = Paths.get(dirPath);
        Files.createDirectories(path);
    }

    // 删除文件或目录
    public static void delete(String path) throws IOException {
   
        Files.deleteIfExists(Paths.get(path));
    }

    // 复制文件
    public static void copy(String source, String target) throws IOException {
   
        Path sourcePath = Paths.get(source);
        Path targetPath = Paths.get(target);
        Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
    }

    // 移动文件
    public static void move(String source, String target) throws IOException {
   
        Path sourcePath = Paths.get(source);
        Path targetPath = Paths.get(target);
        Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
    }

    // 读取文件内容
    public static List<String> readAllLines(String filePath) throws IOException {
   
        Path path = Paths.get(filePath);
        return Files.readAllLines(path);
    }

    // 写入文件内容
    public static void writeLines(String filePath, List<String> lines) throws IOException {
   
        Path path = Paths.get(filePath);
        Files.write(path, lines);
    }
}

二、容器

2.1 Java容器有哪些

实操场景:容器性能对比测试

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ContainerPerformanceTest {
   
    public static void main(String[] args) {
   
        int loopCount = 100000;

        // 测试ArrayList
        testList(new ArrayList<>(), loopCount);

        // 测试LinkedList
        testList(new LinkedList<>(), loopCount);

        // 测试HashMap
        testMap(new HashMap<>(), loopCount);

        // 测试ConcurrentHashMap
        testMap(new ConcurrentHashMap<>(), loopCount);
    }

    private static void testList(List<Integer> list, int count) {
   
        long startTime = System.currentTimeMillis();

        // 添加元素
        for (int i = 0; i < count; i++) {
   
            list.add(i);
        }

        // 随机访问元素
        for (int i = 0; i < count; i++) {
   
            list.get(i);
        }

        long endTime = System.currentTimeMillis();
        System.out.println(list.getClass().getSimpleName() + "耗时: " + (endTime - startTime) + "ms");
    }

    private static void testMap(Map<Integer, Integer> map, int count) {
   
        long startTime = System.currentTimeMillis();

        // 添加元素
        for (int i = 0; i < count; i++) {
   
            map.put(i, i);
        }

        // 随机访问元素
        for (int i = 0; i < count; i++) {
   
            map.get(i);
        }

        long endTime = System.currentTimeMillis();
        System.out.println(map.getClass().getSimpleName() + "耗时: " + (endTime - startTime) + "ms");
    }
}

2.2 HashMap相关问题

实操场景:自定义HashMap实现

import java.util.LinkedList;

public class CustomHashMap<K, V> {
   
    private static final int DEFAULT_CAPACITY = 16;
    private LinkedList<Entry<K, V>>[] table;

    public CustomHashMap() {
   
        table = new LinkedList[DEFAULT_CAPACITY];
        for (int i = 0; i < DEFAULT_CAPACITY; i++) {
   
            table[i] = new LinkedList<>();
        }
    }

    public void put(K key, V value) {
   
        int index = getIndex(key);
        LinkedList<Entry<K, V>> bucket = table[index];

        // 检查是否已存在相同key
        for (Entry<K, V> entry : bucket) {
   
            if (entry.key.equals(key)) {
   
                entry.value = value;
                return;
            }
        }

        // 添加新元素
        bucket.add(new Entry<>(key, value));
    }

    public V get(K key) {
   
        int index = getIndex(key);
        LinkedList<Entry<K, V>> bucket = table[index];

        for (Entry<K, V> entry : bucket) {
   
            if (entry.key.equals(key)) {
   
                return entry.value;
            }
        }

        return null;
    }

    private int getIndex(K key) {
   
        return Math.abs(key.hashCode()) % DEFAULT_CAPACITY;
    }

    static class Entry<K, V> {
   
        K key;
        V value;

        public Entry(K key, V value) {
   
            this.key = key;
            this.value = value;
        }
    }
}

2.3 ConcurrentHashMap相关问题

实操场景:多线程环境下的并发操作

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ConcurrentHashMapDemo {
   
    private static final int THREAD_COUNT = 10;
    private static final int LOOP_COUNT = 1000;

    public static void main(String[] args) throws InterruptedException {
   
        ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);

        // 多线程并发写入
        for (int i = 0; i < THREAD_COUNT; i++) {
   
            final int threadId = i;
            executor.submit(() -> {
   
                for (int j = 0; j < LOOP_COUNT; j++) {
   
                    map.put(threadId * LOOP_COUNT + j, j);
                }
            });
        }

        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES);

        // 验证结果
        System.out.println("Map size: " + map.size());
        System.out.println("Expected size: " + (THREAD_COUNT * LOOP_COUNT));
    }
}

2.4 LinkedList适合用什么排序

代码示例:实现归并排序对LinkedList排序

import java.util.LinkedList;

public class LinkedListMergeSort {
   
    public static <T extends Comparable<T>> LinkedList<T> sort(LinkedList<T> list) {
   
        if (list == null || list.size() <= 1) {
   
            return list;
        }

        // 分割链表
        LinkedList<T> left = new LinkedList<>();
        LinkedList<T> right = new LinkedList<>();
        int mid = list.size() / 2;

        for (int i = 0; i < mid; i++) {
   
            left.add(list.removeFirst());
        }
        right.addAll(list);

        // 递归排序左右两部分
        left = sort(left);
        right = sort(right);

        // 合并已排序的链表
        return merge(left, right);
    }

    private static <T extends Comparable<T>> LinkedList<T> merge(LinkedList<T> left, LinkedList<T> right) {
   
        LinkedList<T> result = new LinkedList<>();

        while (!left.isEmpty() && !right.isEmpty()) {
   
            if (left.peek().compareTo(right.peek()) <= 0) {
   
                result.add(left.removeFirst());
            } else {
   
                result.add(right.removeFirst());
            }
        }

        // 添加剩余元素
        result.addAll(left);
        result.addAll(right);

        return result;
    }
}

三、多线程

3.1 创建线程的方式

代码示例:三种创建线程的方式

// 1. 继承Thread类
class MyThread extends Thread {
   
    @Override
    public void run() {
   
        System.out.println("继承Thread类创建的线程: " + Thread.currentThread().getName());
    }
}

// 2. 实现Runnable接口
class MyRunnable implements Runnable {
   
    @Override
    public void run() {
   
        System.out.println("实现Runnable接口创建的线程: " + Thread.currentThread().getName());
    }
}

// 3. 实现Callable接口
import java.util.concurrent.*;

class MyCallable implements Callable<String> {
   
    @Override
    public String call() throws Exception {
   
        return "实现Callable接口创建的线程: " + Thread.currentThread().getName();
    }
}

public class ThreadCreationDemo {
   
    public static void main(String[] args) throws ExecutionException, InterruptedException {
   
        // 方式1: 继承Thread类
        MyThread thread1 = new MyThread();
        thread1.start();

        // 方式2: 实现Runnable接口
        Thread thread2 = new Thread(new MyRunnable());
        thread2.start();

        // 方式3: 实现Callable接口
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new MyCallable());
        System.out.println(future.get());
        executor.shutdown();
    }
}

3.2 线程池相关问题

实操场景:自定义线程池配置

import java.util.concurrent.*;

public class ThreadPoolDemo {
   
    public static void main(String[] args) {
   
        // 创建自定义线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,                   // 核心线程数
                10,                  // 最大线程数
                60,                  // 空闲线程存活时间
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),  // 任务队列
                Executors.defaultThreadFactory(), // 线程工厂
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );

        // 提交任务
        for (int i = 0; i < 20; i++) {
   
            final int taskId = i;
            executor.submit(() -> {
   
                System.out.println("Task " + taskId + " is running on thread: " + Thread.currentThread().getName());
                try {
   
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
                System.out.println("Task " + taskId + " completed");
            });
        }

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

3.3 线程安全问题

代码示例:使用synchronized和Lock实现线程安全

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// 1. 使用synchronized关键字
class SynchronizedCounter {
   
    private int count = 0;

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

    public synchronized int getCount() {
   
        return count;
    }
}

// 2. 使用Lock接口
class LockCounter {
   
    private int count = 0;
    private final Lock lock = new ReentrantLock();

    public void increment() {
   
        lock.lock();
        try {
   
            count++;
        } finally {
   
            lock.unlock();
        }
    }

    public int getCount() {
   
        lock.lock();
        try {
   
            return count;
        } finally {
   
            lock.unlock();
        }
    }
}

// 3. 使用原子类
import java.util.concurrent.atomic.AtomicInteger;

class AtomicCounter {
   
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
   
        count.incrementAndGet();
    }

    public int getCount() {
   
        return count.get();
    }
}

3.4 AQS相关问题

代码示例:自定义锁实现

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

class CustomLock {
   
    private static class Sync extends AbstractQueuedSynchronizer {
   
        @Override
        protected boolean tryAcquire(int arg) {
   
            if (compareAndSetState(0, 1)) {
   
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
   
            if (getState() == 0) {
   
                throw new IllegalMonitorStateException();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        @Override
        protected boolean isHeldExclusively() {
   
            return getState() == 1;
        }
    }

    private final Sync sync = new Sync();

    public void lock() {
   
        sync.acquire(1);
    }

    public void unlock() {
   
        sync.release(1);
    }

    public boolean tryLock() {
   
        return sync.tryAcquire(1);
    }
}

四、JVM

4.1 JVM内存区域划分

实操场景:内存溢出测试

import java.util.ArrayList;
import java.util.List;

public class OutOfMemoryDemo {
   
    public static void main(String[] args) {
   
        // 堆内存溢出
        heapOutOfMemory();

        // 栈内存溢出
        // stackOverflow();
    }

    private static void heapOutOfMemory() {
   
        List<byte[]> list = new ArrayList<>();
        while (true) {
   
            list.add(new byte[1024 * 1024]); // 每次添加1MB数据
        }
    }

    private static void stackOverflow() {
   
        stackOverflow(); // 递归调用导致栈溢出
    }
}

4.2 垃圾回收机制

实操场景:GC日志分析

# 运行程序时开启GC日志
java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xms256m -Xmx256m OutOfMemoryDemo

# 典型GC日志分析
2025-06-26T10:30:45.123+0800: 0.234: [GC (Allocation Failure) [PSYoungGen: 65536K->256K(76288K)] 65536K->65536K(251392K), 0.0012345 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

# 日志解读:
# 1. GC发生时间: 2025-06-26T10:30:45.123+0800
# 2. GC类型: 新生代GC (Allocation Failure表示内存分配失败触发GC)
# 3. 新生代内存变化: 65536K->256K(76288K)
# 4. 堆内存变化: 65536K->65536K(251392K)
# 5. GC耗时: 0.0012345秒

4.3 类加载机制

代码示例:自定义类加载器

import java.io.*;

public class CustomClassLoader extends ClassLoader {
   
    private String classPath;

    public CustomClassLoader(String classPath) {
   
        this.classPath = classPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
   
        try {
   
            byte[] classData = loadClassData(name);
            if (classData == null) {
   
                throw new ClassNotFoundException();
            }
            return defineClass(name, classData, 0, classData.length);
        } catch (IOException e) {
   
            throw new ClassNotFoundException(name, e);
        }
    }

    private byte[] loadClassData(String name) throws IOException {
   
        String path = classPath + File.separatorChar +
                name.replace('.', File.separatorChar) + ".class";

        try (InputStream is = new FileInputStream(path);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
   

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
   
                bos.write(buffer, 0, bytesRead);
            }
            return bos.toByteArray();
        }
    }

    public static void main(String[] args) throws Exception {
   
        CustomClassLoader loader = new CustomClassLoader("/path/to/classes");
        Class<?> clazz = loader.loadClass("com.example.MyClass");
        Object obj = clazz.getDeclaredConstructor().newInstance();
        System.out.println(obj.getClass().getClassLoader());
    }
}

4.4 JVM性能调优

实操场景:JVM参数配置

# 典型的JVM性能调优参数配置示例
java -Xms512m -Xmx512m -Xmn256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m \
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/java_heapdump.hprof \
-jar myapplication.jar

# 参数说明:
# -Xms512m: 初始堆大小512MB
# -Xmx512m: 最大堆大小512MB
# -Xmn256m: 新生代大小256MB
# -XX:MetaspaceSize=128m: 元空间初始大小128MB
# -XX:MaxMetaspaceSize=256m: 元空间最大大小256MB
# -XX:+UseG1GC: 使用G1垃圾收集器
# -XX:MaxGCPauseMillis=200: 最大GC停顿时间200毫秒
# -XX:+HeapDumpOnOutOfMemoryError: 发生OOM时生成堆转储文件
# -XX:HeapDumpPath=/var/log/java_heapdump.hprof: 堆转储文件路径

五、数据库

5.1 MySQL索引优化

实操场景:索引优化测试

-- 创建测试表
CREATE TABLE user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    age INT,
    gender VARCHAR(10),
    email VARCHAR(100),
    create_time DATETIME
);

-- 添加测试数据
INSERT INTO user (name, age, gender, email, create_time)
VALUES ('张三', 25, '男', 'zhangsan@example.com', NOW()),
       ('李四', 30, '男', 'lisi@example.com', NOW()),
       ('王五', 28, '女', 'wangwu@example.com', NOW());

-- 创建复合索引
CREATE INDEX idx_name_age_gender ON user (name, age, gender);

-- 执行计划分析
EXPLAIN SELECT * FROM user WHERE name = '张三' AND age = 25 AND gender = '男';

-- 索引覆盖测试
EXPLAIN SELECT name, age, gender FROM user WHERE name = '张三';

5.2 数据库事务隔离级别

实操场景:演示脏读、不可重复读和幻读

-- 设置事务隔离级别为读未提交(会出现脏读)
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- 会话1: 开启事务
START TRANSACTION;
UPDATE user SET age = 31 WHERE name = '李四';

-- 会话2: 查询(会读到未提交的数据,出现脏读)
SELECT * FROM user WHERE name = '李四';

-- 会话1: 回滚事务
ROLLBACK;

-- 设置事务隔离级别为可重复读(MySQL默认级别,解决不可重复读,但可能出现幻读)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 会话1: 开启事务并查询
START TRANSACTION;
SELECT * FROM user WHERE age > 25;

-- 会话2: 插入新记录
INSERT INTO user (name, age, gender) VALUES ('赵六', 35, '男');
COMMIT;

-- 会话1: 再次查询(两次查询结果一致,解决不可重复读)
SELECT * FROM user WHERE age > 25;

-- 会话1: 插入相同条件的记录(会出现Duplicate key错误,说明出现幻读)
INSERT INTO user (name, age, gender) VALUES ('赵六', 35, '男');

5.3 MySQL主从复制

实操场景:配置MySQL主从复制

# 主库配置 (my.cnf)
[mysqld]
server-id=1
log-bin=mysql-bin
binlog-do-db=test_db

# 从库配置 (my.cnf)
[mysqld]
server-id=2
relay-log=mysql-relay-bin
log-bin=mysql-bin

# 主库操作
CREATE USER 'repl_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;
SHOW MASTER STATUS;

# 从库操作
CHANGE MASTER TO
    MASTER_HOST='主库IP',
    MASTER_USER='repl_user',
    MASTER_PASSWORD='password',
    MASTER_LOG_FILE='mysql-bin.xxxxxx',
    MASTER_LOG_POS=xxxxxx;

START SLAVE;
SHOW SLAVE STATUS\G

六、算法

6.1 排序算法

代码示例:实现快速排序

public class QuickSort {
   
    public static void sort(int[] arr) {
   
        if (arr == null || arr.length <= 1) {
   
            return;
        }
        quickSort(arr, 0, arr.length - 1);
    }

    private static void quickSort(int[] arr, int left, int right) {
   
        if (left < right) {
   
            int pivotIndex = partition(arr, left, right);
            quickSort(arr, left, pivotIndex - 1);
            quickSort(arr, pivotIndex + 1, right);
        }
    }

    private static int partition(int[] arr, int left, int right) {
   
        int pivot = arr[right];
        int i = left - 1;

        for (int j = left; j < right; j++) {
   
            if (arr[j] <= pivot) {
   
                i++;
                swap(arr, i, j);
            }
        }

        swap(arr, i + 1, right);
        return i + 1;
    }

    private static void swap(int[] arr, int i, int j) {
   
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

6.2 查找算法

代码示例:实现二分查找

public class BinarySearch {
   
    public static int search(int[] arr, int target) {
   
        int left = 0;
        int right = arr.length - 1;

        while (left <= right) {
   
            int mid = left + (right - left) / 2;

            if (arr[mid] == target) {
   
                return mid;
            } else if (arr[mid] < target) {
   
                left = mid + 1;
            } else {
   
                right = mid - 1;
            }
        }

        return -1; // 未找到
    }
}

6.3 递归与动态规划

代码示例:斐波那契数列(动态规划优化)

public class Fibonacci {
   
    // 递归实现(效率低)
    public static int fibRecursive(int n) {
   
        if (n <= 1) {
   
            return n;
        }
        return fibRecursive(n - 1) + fibRecursive(n - 2);
    }

    // 动态规划实现(高效)
    public static int fibDynamic(int n) {
   
        if (n <= 1) {
   
            return n;
        }

        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = 1;

        for (int i = 2; i <= n; i++) {
   
            dp[i] = dp[i - 1] + dp[i - 2];
        }

        return dp[n];
    }

    // 优化空间复杂度的动态规划
    public static int fibOptimized(int n) {
   
        if (n <= 1) {
   
            return n;
        }

        int a = 0;
        int b = 1;
        int result = 0;

        for (int i = 2; i <= n; i++) {
   
            result = a + b;
            a = b;
            b = result;
        }

        return result;
    }
}

6.4 链表操作

代码示例:反转链表

class ListNode {
   
    int val;
    ListNode next;
    ListNode(int x) {
    val = x; }
}

public class ReverseLinkedList {
   
    // 迭代方法
    public static ListNode reverseList(ListNode head) {
   
        ListNode prev = null;
        ListNode curr = head;

        while (curr != null) {
   
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }

        return prev;
    }

    // 递归方法
    public static ListNode reverseListRecursive(ListNode head) {
   
        if (head == null || head.next == null) {
   
            return head;
        }

        ListNode newHead = reverseListRecursive(head.next);
        head.next.next = head;
        head.next = null;

        return newHead;
    }
}

以上代码示例和实操场景展示了Java开发中的核心技术点和面试高频考点。通过实际动手操作这些示例,你可以更深入地理解相关概念和技术,为面试做好充分准备。


Java 开发岗,Java 架构师,百度校招,面试题,历年经典,Java 基础,数据结构,算法,并发编程,JVM,Spring 框架,MySQL, 分布式,微服务,设计模式



代码获取方式
https://pan.quark.cn/s/14fcf913bae6


相关文章
|
7月前
|
消息中间件 Java Kafka
Java 事件驱动架构设计实战与 Kafka 生态系统组件实操全流程指南
本指南详解Java事件驱动架构与Kafka生态实操,涵盖环境搭建、事件模型定义、生产者与消费者实现、事件测试及高级特性,助你快速构建高可扩展分布式系统。
364 7
|
7月前
|
消息中间件 Java 数据库
Java 基于 DDD 分层架构实战从基础到精通最新实操全流程指南
本文详解基于Java的领域驱动设计(DDD)分层架构实战,结合Spring Boot 3.x、Spring Data JPA 3.x等最新技术栈,通过电商订单系统案例展示如何构建清晰、可维护的微服务架构。内容涵盖项目结构设计、各层实现细节及关键技术点,助力开发者掌握DDD在复杂业务系统中的应用。
1358 0
|
9月前
|
缓存 Java 关系型数据库
2025 年最新华为 Java 面试题及答案,全方位打造面试宝典
Java面试高频考点与实践指南(150字摘要) 本文系统梳理了Java面试核心考点,包括Java基础(数据类型、面向对象特性、常用类使用)、并发编程(线程机制、锁原理、并发容器)、JVM(内存模型、GC算法、类加载机制)、Spring框架(IoC/AOP、Bean生命周期、事务管理)、数据库(MySQL引擎、事务隔离、索引优化)及分布式(CAP理论、ID生成、Redis缓存)。同时提供华为级实战代码,涵盖Spring Cloud Alibaba微服务、Sentinel限流、Seata分布式事务,以及完整的D
492 1
|
6月前
|
算法 Java
50道java集合面试题
50道 java 集合面试题
|
8月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
583 0
|
5月前
|
负载均衡 Java API
grpc-java 架构学习指南
本指南系统解析 grpc-java 架构,涵盖分层设计、核心流程与源码结构,结合实战路径与调试技巧,助你从入门到精通,掌握高性能 RPC 开发精髓。
561 8
|
8月前
|
Java 数据库连接 数据库
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
本文全面总结了Java核心知识点,涵盖基础语法、面向对象、集合框架、并发编程、网络编程及主流框架如Spring生态、MyBatis等,结合JVM原理与性能优化技巧,并通过一个学生信息管理系统的实战案例,帮助你快速掌握Java开发技能,适合Java学习与面试准备。
372 2
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
|
6月前
|
算法 Java
50道java基础面试题
50道java基础面试题
|
7月前
|
机器学习/深度学习 人工智能 Java
Java 技术支撑下 AI 与 ML 技术融合的架构设计与落地案例分析
摘要: Java与AI/ML技术的融合为智能化应用提供了强大支持。通过选用Deeplearning4j、DJL等框架解决技术适配问题,并结合Spring生态和JVM优化提升性能。在金融风控、智能制造、医疗影像等领域实现了显著效果,如审批效率提升3倍、设备停机减少41%、医疗诊断延迟降低80%。这种技术融合推动了多行业的智能化升级,展现了广阔的应用前景。
546 0

热门文章

最新文章