1. JAVA高频代码题解析与实战
作为从业十年的Java开发者,我整理了面试中最常出现的20类代码题型及其解题思路。这些题目不仅考察基础语法,更能检验候选人对Java核心机制的理解深度。以下是经过上百场面试验证的必考题型精要。
2. 基础语法类题型
2.1 字符串处理三连考
java复制// 1. 字符串反转
public String reverseString(String input) {
return new StringBuilder(input).reverse().toString();
}
// 2. 判断回文
public boolean isPalindrome(String str) {
return str.equals(new StringBuilder(str).reverse().toString());
}
// 3. 统计字符出现次数
public Map<Character, Integer> countChars(String s) {
return s.chars()
.mapToObj(c -> (char)c)
.collect(Collectors.groupingBy(Function.identity(),
Collectors.summingInt(c -> 1)));
}
关键点:StringBuilder线程不安全但性能好,面试常问与StringBuffer的区别。统计字符次数的Java8流式写法是加分项。
2.2 数组/集合操作
java复制// 1. 寻找数组第二大的数
public int findSecondLargest(int[] arr) {
int first = Integer.MIN_VALUE, second = Integer.MIN_VALUE;
for (int num : arr) {
if (num > first) {
second = first;
first = num;
} else if (num > second && num != first) {
second = num;
}
}
return second;
}
// 2. 合并两个有序数组
public int[] mergeSortedArrays(int[] a, int[] b) {
int[] result = new int[a.length + b.length];
int i = 0, j = 0, k = 0;
while (i < a.length && j < b.length) {
result[k++] = a[i] < b[j] ? a[i++] : b[j++];
}
System.arraycopy(a, i, result, k, a.length - i);
System.arraycopy(b, j, result, k, b.length - j);
return result;
}
3. 面向对象核心题型
3.1 单例模式的三重考验
java复制// 1. 饿汉式(线程安全)
public class SingletonA {
private static final SingletonA INSTANCE = new SingletonA();
private SingletonA() {}
public static SingletonA getInstance() {
return INSTANCE;
}
}
// 2. 双重检查锁(延迟加载)
public class SingletonB {
private volatile static SingletonB instance;
private SingletonB() {}
public static SingletonB getInstance() {
if (instance == null) {
synchronized (SingletonB.class) {
if (instance == null) {
instance = new SingletonB();
}
}
}
return instance;
}
}
// 3. 枚举实现(防反射攻击)
public enum SingletonC {
INSTANCE;
public void doSomething() {
// 业务方法
}
}
避坑指南:volatile关键字防止指令重排序是高频考点,枚举单例是《Effective Java》推荐写法。
3.2 工厂模式实战
java复制interface Shape {
void draw();
}
class Circle implements Shape {
@Override public void draw() {
System.out.println("Drawing Circle");
}
}
class ShapeFactory {
public Shape getShape(String shapeType) {
if (shapeType == null) return null;
if (shapeType.equalsIgnoreCase("CIRCLE")) {
return new Circle();
}
// 其他形状...
return null;
}
}
4. 多线程必考题
4.1 生产者-消费者问题
java复制class Buffer {
private Queue<Integer> queue = new LinkedList<>();
private int capacity;
public Buffer(int capacity) {
this.capacity = capacity;
}
public synchronized void produce(int item) throws InterruptedException {
while (queue.size() == capacity) {
wait();
}
queue.offer(item);
notifyAll();
}
public synchronized int consume() throws InterruptedException {
while (queue.isEmpty()) {
wait();
}
int item = queue.poll();
notifyAll();
return item;
}
}
4.2 线程交替打印
java复制class AlternatePrint {
private static final Object lock = new Object();
private static int count = 1;
private static final int MAX = 100;
public static void main(String[] args) {
new Thread(() -> {
synchronized (lock) {
while (count <= MAX) {
if (count % 2 == 1) {
System.out.println(Thread.currentThread().getName() + ": " + count++);
lock.notify();
} else {
try { lock.wait(); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}, "OddThread").start();
new Thread(() -> {
synchronized (lock) {
while (count <= MAX) {
if (count % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ": " + count++);
lock.notify();
} else {
try { lock.wait(); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}, "EvenThread").start();
}
}
5. 算法与数据结构
5.1 二叉树遍历
java复制class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
// 前序遍历(递归)
public void preOrder(TreeNode root) {
if (root != null) {
System.out.print(root.val + " ");
preOrder(root.left);
preOrder(root.right);
}
}
// 层序遍历(队列)
public void levelOrder(TreeNode root) {
if (root == null) return;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
System.out.print(node.val + " ");
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
5.2 LRU缓存实现
java复制class LRUCache {
class DLinkedNode {
int key, value;
DLinkedNode prev, next;
}
private Map<Integer, DLinkedNode> cache = new HashMap<>();
private int size, capacity;
private DLinkedNode head, tail;
public LRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
head = new DLinkedNode();
tail = new DLinkedNode();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
DLinkedNode node = cache.get(key);
if (node == null) return -1;
moveToHead(node);
return node.value;
}
public void put(int key, int value) {
DLinkedNode node = cache.get(key);
if (node == null) {
node = new DLinkedNode();
node.key = key;
node.value = value;
cache.put(key, node);
addNode(node);
if (++size > capacity) {
DLinkedNode tail = popTail();
cache.remove(tail.key);
--size;
}
} else {
node.value = value;
moveToHead(node);
}
}
private void addNode(DLinkedNode node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void removeNode(DLinkedNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void moveToHead(DLinkedNode node) {
removeNode(node);
addNode(node);
}
private DLinkedNode popTail() {
DLinkedNode res = tail.prev;
removeNode(res);
return res;
}
}
6. Java8新特性
6.1 Stream API实战
java复制List<Employee> employees = Arrays.asList(
new Employee("John", 25, 50000),
new Employee("Jane", 30, 60000)
);
// 1. 过滤与映射
List<String> names = employees.stream()
.filter(e -> e.getSalary() > 55000)
.map(Employee::getName)
.collect(Collectors.toList());
// 2. 分组统计
Map<Integer, List<Employee>> byAge = employees.stream()
.collect(Collectors.groupingBy(Employee::getAge));
// 3. 并行流计算
double avgSalary = employees.parallelStream()
.mapToDouble(Employee::getSalary)
.average()
.orElse(0);
6.2 Optional使用技巧
java复制public String getCity(User user) {
return Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCity)
.orElse("Unknown");
}
7. 异常处理与IO
7.1 文件拷贝最佳实践
java复制public void copyFile(File source, File dest) throws IOException {
try (InputStream in = new FileInputStream(source);
OutputStream out = new FileOutputStream(dest)) {
byte[] buffer = new byte[8192];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
}
}
7.2 自定义异常设计
java复制class BusinessException extends RuntimeException {
private ErrorCode errorCode;
public BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
public ErrorCode getErrorCode() {
return errorCode;
}
}
enum ErrorCode {
INVALID_INPUT(400, "Invalid input"),
NOT_FOUND(404, "Resource not found");
private final int code;
private final String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
public String getMessage() {
return message;
}
}
8. 综合设计题
8.1 实现阻塞队列
java复制class MyBlockingQueue<T> {
private Queue<T> queue = new LinkedList<>();
private int capacity;
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public MyBlockingQueue(int capacity) {
this.capacity = capacity;
}
public void put(T item) throws InterruptedException {
lock.lock();
try {
while (queue.size() == capacity) {
notFull.await();
}
queue.add(item);
notEmpty.signal();
} finally {
lock.unlock();
}
}
public T take() throws InterruptedException {
lock.lock();
try {
while (queue.isEmpty()) {
notEmpty.await();
}
T item = queue.remove();
notFull.signal();
return item;
} finally {
lock.unlock();
}
}
}
8.2 设计缓存系统
java复制interface Cache<K, V> {
V get(K key);
void put(K key, V value);
void delete(K key);
void clear();
}
class MemoryCache<K, V> implements Cache<K, V> {
private final Map<K, V> cache;
private final int maxSize;
public MemoryCache(int maxSize) {
this.maxSize = maxSize;
this.cache = new LinkedHashMap<K, V>(maxSize, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
};
}
@Override
public V get(K key) {
return cache.get(key);
}
@Override
public void put(K key, V value) {
cache.put(key, value);
}
@Override
public void delete(K key) {
cache.remove(key);
}
@Override
public void clear() {
cache.clear();
}
}
9. 高频面试问题解析
9.1 HashMap原理
- 数组+链表/红黑树结构
- 默认负载因子0.75
- 扩容机制:2倍扩容,rehash
- 线程不安全表现:死循环、数据丢失
9.2 JVM内存模型
- 程序计数器:线程私有
- 虚拟机栈:栈帧存储局部变量表等
- 本地方法栈
- 堆:对象实例
- 方法区:类信息、常量池
9.3 Spring循环依赖
- 三级缓存解决:
- singletonObjects:完整Bean
- earlySingletonObjects:早期引用
- singletonFactories:ObjectFactory
10. 代码优化技巧
10.1 字符串拼接
java复制// 错误示范(产生大量中间对象)
String result = "";
for (int i = 0; i < 100; i++) {
result += i;
}
// 正确写法
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append(i);
}
String result = sb.toString();
10.2 避免自动装箱
java复制// 低效写法
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i; // 发生自动装箱
}
// 高效写法
long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
11. 单元测试规范
11.1 JUnit最佳实践
java复制class CalculatorTest {
@BeforeEach
void setUp() {
// 初始化代码
}
@Test
@DisplayName("加法测试")
void testAdd() {
assertEquals(5, Calculator.add(2, 3));
assertThrows(IllegalArgumentException.class,
() -> Calculator.add(null, 3));
}
@ParameterizedTest
@CsvSource({"1,2,3", "4,5,9"})
void parameterizedTest(int a, int b, int expected) {
assertEquals(expected, Calculator.add(a, b));
}
}
11.2 Mockito使用
java复制class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
void testGetUser() {
User mockUser = new User("test");
when(userRepository.findById(anyLong()))
.thenReturn(Optional.of(mockUser));
User result = userService.getUser(1L);
assertEquals("test", result.getName());
verify(userRepository).findById(1L);
}
}
12. 并发工具类实战
12.1 CountDownLatch应用
java复制class ParallelProcessor {
public void process(List<Task> tasks) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(4);
CountDownLatch latch = new CountDownLatch(tasks.size());
for (Task task : tasks) {
executor.submit(() -> {
try {
task.execute();
} finally {
latch.countDown();
}
});
}
latch.await();
executor.shutdown();
System.out.println("All tasks completed");
}
}
12.2 CompletableFuture组合
java复制CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
CompletableFuture<String> combined = future1.thenCombine(future2,
(s1, s2) -> s1 + " " + s2);
combined.thenAccept(System.out::println);
13. 设计模式进阶
13.1 观察者模式
java复制interface Observer {
void update(String message);
}
class ConcreteObserver implements Observer {
@Override
public void update(String message) {
System.out.println("Received: " + message);
}
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer o) {
observers.add(o);
}
public void notifyObservers(String message) {
for (Observer o : observers) {
o.update(message);
}
}
}
13.2 装饰器模式
java复制interface Coffee {
double getCost();
String getDescription();
}
class SimpleCoffee implements Coffee {
@Override public double getCost() { return 1.0; }
@Override public String getDescription() { return "Simple coffee"; }
}
abstract class CoffeeDecorator implements Coffee {
protected final Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public double getCost() {
return decoratedCoffee.getCost();
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription();
}
}
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override public double getCost() { return super.getCost() + 0.5; }
@Override public String getDescription() {
return super.getDescription() + ", with milk";
}
}
14. JVM调优实战
14.1 内存溢出排查
java复制// 模拟内存泄漏
public class MemoryLeak {
static List<Object> leakList = new ArrayList<>();
public static void main(String[] args) {
while (true) {
leakList.add(new byte[1024 * 1024]); // 每次添加1MB
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
排查步骤:
- jps -l 查看进程ID
- jmap -histo:live pid | head -20 查看对象分布
- jstat -gcutil pid 1000 监控GC情况
- MAT分析heap dump
14.2 GC日志分析
bash复制# JVM参数示例
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintHeapAtGC
-Xloggc:/path/to/gc.log
典型GC日志解读:
code复制[GC (Allocation Failure) [PSYoungGen: 65536K->10720K(76288K)]
65536K->10728K(251392K), 0.0118329 secs]
- PSYoungGen:Parallel Scavenge收集器
- 65536K->10720K:回收前->回收后年轻代占用
- (76288K):年轻代总大小
- 65536K->10728K:整个堆回收前后占用
- 0.0118329 secs:耗时
15. 反射与动态代理
15.1 反射API实战
java复制class ReflectionDemo {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("java.util.ArrayList");
// 创建实例
Object list = clazz.getDeclaredConstructor().newInstance();
// 调用方法
Method addMethod = clazz.getMethod("add", Object.class);
addMethod.invoke(list, "Hello");
// 访问字段
Field sizeField = clazz.getDeclaredField("size");
sizeField.setAccessible(true);
System.out.println("Size: " + sizeField.get(list));
}
}
15.2 JDK动态代理
java复制interface Service {
void serve();
}
class RealService implements Service {
@Override public void serve() {
System.out.println("Real service working");
}
}
class LoggingHandler implements InvocationHandler {
private final Object target;
public LoggingHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After method: " + method.getName());
return result;
}
}
public class DynamicProxyDemo {
public static void main(String[] args) {
Service realService = new RealService();
Service proxy = (Service) Proxy.newProxyInstance(
Service.class.getClassLoader(),
new Class[]{Service.class},
new LoggingHandler(realService)
);
proxy.serve();
}
}
16. 网络编程核心
16.1 Socket通信
java复制// 服务端
public class EchoServer {
public static void main(String[] args) throws IOException {
try (ServerSocket server = new ServerSocket(8080)) {
System.out.println("Server started");
while (true) {
Socket client = server.accept();
new Thread(() -> handleClient(client)).start();
}
}
}
private static void handleClient(Socket client) {
try (BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(
client.getOutputStream(), true)) {
String input;
while ((input = in.readLine()) != null) {
out.println("Echo: " + input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 客户端
public class EchoClient {
public static void main(String[] args) throws IOException {
try (Socket socket = new Socket("localhost", 8080);
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in))) {
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println(in.readLine());
}
}
}
}
16.2 HTTP客户端
java复制class HttpClientExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.GET()
.build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body());
}
}
17. 数据库编程
17.1 JDBC事务
java复制public void transferFunds(Connection conn,
int fromId, int toId, double amount) throws SQLException {
try {
conn.setAutoCommit(false);
// 扣款
try (PreparedStatement stmt = conn.prepareStatement(
"UPDATE accounts SET balance = balance - ? WHERE id = ?")) {
stmt.setDouble(1, amount);
stmt.setInt(2, fromId);
stmt.executeUpdate();
}
// 存款
try (PreparedStatement stmt = conn.prepareStatement(
"UPDATE accounts SET balance = balance + ? WHERE id = ?")) {
stmt.setDouble(1, amount);
stmt.setInt(2, toId);
stmt.executeUpdate();
}
conn.commit();
} catch (SQLException e) {
conn.rollback();
throw e;
} finally {
conn.setAutoCommit(true);
}
}
17.2 连接池配置
java复制// HikariCP配置示例
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("user");
config.setPassword("password");
config.setMaximumPoolSize(10);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
HikariDataSource ds = new HikariDataSource(config);
18. 安全编程要点
18.1 密码加密存储
java复制public class PasswordUtil {
private static final int ITERATIONS = 65536;
private static final int KEY_LENGTH = 256;
private static final String ALGORITHM = "PBKDF2WithHmacSHA256";
public static String hashPassword(char[] password, byte[] salt) {
PBEKeySpec spec = new PBEKeySpec(password, salt, ITERATIONS, KEY_LENGTH);
try {
SecretKeyFactory skf = SecretKeyFactory.getInstance(ALGORITHM);
byte[] hash = skf.generateSecret(spec).getEncoded();
return Base64.getEncoder().encodeToString(hash);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
spec.clearPassword();
}
}
public static boolean verifyPassword(char[] password,
byte[] salt, String storedHash) {
String newHash = hashPassword(password, salt);
return MessageDigest.isEqual(
Base64.getDecoder().decode(newHash),
Base64.getDecoder().decode(storedHash)
);
}
}
18.2 SQL注入防护
java复制// 错误示范(存在注入风险)
String query = "SELECT * FROM users WHERE username = '" + input + "'";
// 正确写法(使用预编译语句)
String sql = "SELECT * FROM users WHERE username = ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, input);
ResultSet rs = stmt.executeQuery();
// 处理结果集
}
19. 性能优化技巧
19.1 对象复用池
java复制class ObjectPool<T> {
private final Supplier<T> creator;
private final Queue<T> pool = new ConcurrentLinkedQueue<>();
public ObjectPool(Supplier<T> creator) {
this.creator = creator;
}
public T borrow() {
T obj = pool.poll();
return obj != null ? obj : creator.get();
}
public void release(T obj) {
pool.offer(obj);
}
}
// 使用示例
ObjectPool<StringBuilder> pool = new ObjectPool<>(StringBuilder::new);
StringBuilder sb = pool.borrow();
try {
sb.append("Hello");
System.out.println(sb.toString());
} finally {
sb.setLength(0);
pool.release(sb);
}
19.2 缓存计算结果
java复制class Fibonacci {
private static final Map<Integer, Long> cache = new ConcurrentHashMap<>();
static {
cache.put(0, 0L);
cache.put(1, 1L);
}
public static long calculate(int n) {
return cache.computeIfAbsent(n,
k -> calculate(k - 1) + calculate(k - 2));
}
}
20. 现代Java特性
20.1 Record类型
java复制record Point(int x, int y) {
public double distanceFromOrigin() {
return Math.hypot(x, y);
}
}
// 使用示例
Point p = new Point(3, 4);
System.out.println(p.x()); // 访问器方法
System.out.println(p.distanceFromOrigin());
20.2 模式匹配
java复制// instanceof模式匹配
if (obj instanceof String s) {
System.out.println(s.length());
}
// switch表达式
String formatted = switch (obj) {
case Integer i -> String.format("int %d", i);
case String s -> String.format("String %s", s);
default -> obj.toString();
};
21. 调试与问题排查
21.1 死锁检测
java复制class DeadlockDetector {
public static void detect() {
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadBean.findDeadlockedThreads();
if (threadIds != null) {
ThreadInfo[] infos = threadBean.getThreadInfo(threadIds);
for (ThreadInfo info : infos) {
System.out.println("Deadlocked thread: " + info.getThreadName());
System.out.println("Lock: " + info.getLockName());
System.out.println("Blocked by: " + info.getLockOwnerName());
for (StackTraceElement ste : info.getStackTrace()) {
System.out.println("\tat " + ste);
}
}
}
}
}
21.2 内存泄漏检测
java复制class LeakDetector {
public static void checkLeaks() {
Runtime rt = Runtime.getRuntime();
long usedMB = (rt.totalMemory() - rt.freeMemory()) / 1024 / 1024;
System.out.println("Memory usage: " + usedMB + "MB");
// 触发GC并检查内存变化
System.gc();
long usedAfterGC = (rt.totalMemory() - rt.freeMemory()) / 1024 / 1024;
if (usedAfterGC > usedMB * 0.8) {
System.out.println("Possible memory leak detected");
}
}
}
22. 编码规范与最佳实践
22.1 防御性编程
java复制// 参数校验
public void process(List<String> items) {
if (items == null) {
throw new IllegalArgumentException("Items cannot be null");
}
if (items.isEmpty()) {
return;
}
// 实际处理逻辑
}
// 不可变集合
public List<String> getItems() {
return Collections.unmodifiableList(items);
}
22.2 资源管理
java复制// try-with-resources最佳实践
public void copyFile(Path src, Path dest) throws IOException {
try (InputStream in = Files.newInputStream(src);
OutputStream out = Files.newOutputStream(dest)) {
byte[] buf = new byte[8192];
int n;
while ((n = in.read(buf)) > 0) {
out.write(buf, 0, n);
}
}
}
23. 微服务相关
23.1 REST API设计
java复制@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
return userService.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User saved = userService.save(user);
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(saved.getId())
.toUri();
return ResponseEntity.created(location).body(saved);
}
}
23.2 服务熔断
java复制@RestController
@DefaultProperties(commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
value = "5000")
})
public class OrderController {
@HystrixCommand(fallbackMethod = "getDefaultOrders")
@GetMapping("/orders/{userId}")
public List<Order> getOrders(@PathVariable Long userId) {
// 调用可能失败的服务
return orderService.getOrders(userId);
}
public List<Order> getDefaultOrders(Long userId) {
return Collections.emptyList();
}
}
24. 实战经验总结
24.1 性能调优案例
某电商系统优化经验:
- 发现ArrayList频繁扩容导致GC压力
- 解决方案:初始化时指定合理容量
- 大量临时String对象产生
- 改用StringBuilder拼接
- 数据库连接泄漏
- 引入连接池并添加监控
24.2 并发问题排查
典型竞态条件场景:
java复制// 错误代码
if (!list.contains(item)) {
list.add(item); // 可能被其他线程插入
}
// 正确写法
synchronized (list) {
if (!list.contains(item)) {
list.add(item);
}
}
// 更优方案
ConcurrentHashMap.putIfAbsent()
25. 持续学习建议
-
深入理解JVM:
- 《深入理解Java虚拟机》
- JVM参数调优实战
-
并发编程进阶:
- Java并发包源码分析
- 无锁编程与CAS原理
-
现代Java特性:
- Project Loom虚拟线程
- Valhalla值类型
-
系统设计能力:
- 分布式系统设计模式
- 微服务架构最佳实践
