当你已经掌握了Java的基础语法,能够编写简单的面向对象程序时,真正的挑战才刚刚开始。Java进阶开发要求你深入理解JVM原理、掌握并发编程、精通设计模式、熟悉企业级开发框架。本文将系统梳理Java进阶开发的核心知识体系,涵盖JVM底层、并发编程、网络编程、数据库访问、框架原理、性能优化等关键领域,助你突破瓶颈,成为一名真正高效的Java开发者。
一、JVM深入:理解Java的运行基石
1.1 JVM内存模型
JVM的内存结构是Java进阶的第一道门槛,理解内存划分对性能调优和问题排查至关重要。
/**
* JVM内存结构
* - 堆(Heap):存储对象实例,线程共享
* - 方法区(Method Area):存储类信息、常量、静态变量,线程共享
* - 虚拟机栈(VM Stack):存储局部变量、操作数栈,线程私有
* - 本地方法栈(Native Method Stack):为Native方法服务
* - 程序计数器(Program Counter):记录当前线程执行的字节码行号
*/
public class JVMMemoryDemo {
// 静态变量存储在方法区
private static int staticVar = 10;
// 常量存储在方法区的运行时常量池
private static final String CONSTANT = "Hello";
public static void main(String[] args) {
// 局部变量存储在虚拟机栈
int localVar = 20;
// 对象存储在堆中
JVMMemoryDemo obj = new JVMMemoryDemo();
// 数组也是对象,存储在堆中
int[] arr = new int[100];
}
}
1.2 垃圾回收机制
GC是Java自动内存管理的核心,理解GC算法和收集器是性能调优的基础。
import java.lang.ref.*;
import java.util.*;
/**
* 垃圾回收基础
* 可达性分析算法:从GC Roots开始,不可达的对象将被回收
* GC Roots包括:
* - 虚拟机栈引用的对象
* - 方法区静态属性引用的对象
* - 方法区常量引用的对象
* - Native方法引用的对象
*/
public class GCDemo {
// 演示引用类型
public static void referenceTypes() {
// 强引用:永不回收
Object strongRef = new Object();
// 软引用:内存不足时回收
SoftReference<Object> softRef = new SoftReference<>(new Object());
// 弱引用:下次GC时回收
WeakReference<Object> weakRef = new WeakReference<>(new Object());
// 虚引用:无法通过它获取对象,主要用于跟踪对象回收
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);
// 手动触发GC(仅建议,不保证立即执行)
System.gc();
System.out.println("强引用:" + strongRef);
System.out.println("软引用:" + softRef.get());
System.out.println("弱引用:" + weakRef.get());
}
// 演示内存泄漏场景
public static void memoryLeak() {
// 场景1:静态集合持有对象引用
List<Object> cache = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
cache.add(new byte[1024 * 1024]); // 每次添加1MB
// 如果不清理,这些对象永远不会被回收
}
// 场景2:未关闭的资源
// try (InputStream is = new FileInputStream("test.txt")) {
// // 自动关闭
// }
// 场景3:监听器未移除
// component.addListener(listener);
// 忘记 component.removeListener(listener);
}
}
1.3 类加载机制
理解类加载过程,掌握双亲委派模型,是开发自定义类加载器和解决类冲突的基础。
/**
* 类加载过程
* 1. 加载:查找并加载类的二进制数据
* 2. 验证:确保加载类的正确性
* 3. 准备:为静态变量分配内存并初始化默认值
* 4. 解析:将符号引用转换为直接引用
* 5. 初始化:执行静态初始化块和静态变量赋值
*/
public class ClassLoaderDemo {
// 演示类加载顺序
static class Parent {
static {
System.out.println("Parent static block");
}
Parent() {
System.out.println("Parent constructor");
}
}
static class Child extends Parent {
static {
System.out.println("Child static block");
}
Child() {
System.out.println("Child constructor");
}
}
public static void main(String[] args) throws Exception {
// 查看类加载器
System.out.println("AppClassLoader: " + ClassLoaderDemo.class.getClassLoader());
System.out.println("ExtClassLoader: " + ClassLoaderDemo.class.getClassLoader().getParent());
System.out.println("BootstrapClassLoader: " +
ClassLoaderDemo.class.getClassLoader().getParent().getParent());
// 演示类加载顺序
System.out.println("=== 第一次创建对象 ===");
new Child();
System.out.println("=== 第二次创建对象 ===");
new Child();
// 自定义类加载器示例
CustomClassLoader customLoader = new CustomClassLoader();
Class<?> clazz = customLoader.loadClass("com.example.MyClass");
System.out.println("加载的类:" + clazz.getName());
}
// 自定义类加载器
static class CustomClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// 从自定义位置加载字节码
byte[] classData = loadClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
}
return defineClass(name, classData, 0, classData.length);
}
private byte[] loadClassData(String name) {
// 实现从文件系统、网络等位置加载类字节码
return null;
}
}
}
二、并发编程:驾驭多线程的力量
2.1 线程基础与生命周期
/**
* 线程生命周期:NEW -> RUNNABLE -> BLOCKED/WAITING/TIMED_WAITING -> TERMINATED
*/
public class ThreadBasics {
// 创建线程的两种方式
public static void createThread() {
// 方式1:继承Thread类
Thread thread1 = new Thread() {
@Override
public void run() {
System.out.println("Thread1 running");
}
};
// 方式2:实现Runnable接口(推荐)
Runnable task = () -> {
System.out.println("Thread2 running");
};
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
}
// 线程状态演示
public static void threadStates() throws InterruptedException {
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000); // TIMED_WAITING状态
synchronized (ThreadBasics.class) {
ThreadBasics.class.wait(); // WAITING状态
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("状态1: " + thread.getState()); // NEW
thread.start();
System.out.println("状态2: " + thread.getState()); // RUNNABLE
Thread.sleep(500);
System.out.println("状态3: " + thread.getState()); // TIMED_WAITING
}
}
2.2 线程同步与锁
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.*;
/**
* 线程同步机制
* - synchronized关键字
* - ReentrantLock可重入锁
* - ReadWriteLock读写锁
* - 原子变量
*/
public class SynchronizationDemo {
// 1. synchronized示例
public static class SynchronizedCounter {
private int count = 0;
// 同步方法
public synchronized void increment() {
count++;
}
// 同步代码块
public void decrement() {
synchronized (this) {
count--;
}
}
public synchronized int getCount() {
return count;
}
}
// 2. ReentrantLock示例
public static class LockCounter {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
// 尝试获取锁(非阻塞)
public boolean tryIncrement() {
if (lock.tryLock()) {
try {
count++;
return true;
} finally {
lock.unlock();
}
}
return false;
}
// 可中断的锁获取
public void incrementWithInterrupt() throws InterruptedException {
lock.lockInterruptibly();
try {
count++;
} finally {
lock.unlock();
}
}
}
// 3. ReadWriteLock读写锁
public static class ReadWriteCounter {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = rwLock.readLock();
private final Lock writeLock = rwLock.writeLock();
private int count = 0;
public int getCount() {
readLock.lock();
try {
return count;
} finally {
readLock.unlock();
}
}
public void increment() {
writeLock.lock();
try {
count++;
} finally {
writeLock.unlock();
}
}
}
// 4. 原子变量(无锁编程)
public static class AtomicCounter {
private final AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // 原子操作
}
public int getCount() {
return count.get();
}
}
// 5. 死锁演示与避免
public static class DeadlockDemo {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
System.out.println("method1获取lock1");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock2) {
System.out.println("method1获取lock2");
}
}
}
public void method2() {
synchronized (lock2) {
System.out.println("method2获取lock2");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lock1) {
System.out.println("method2获取lock1");
}
}
}
// 解决方案:统一锁顺序、使用tryLock、使用更高层次的并发工具
}
}
2.3 并发工具类
import java.util.concurrent.*;
import java.util.*;
/**
* JUC并发工具类
* - CountDownLatch:等待多个线程完成
* - CyclicBarrier:循环屏障,等待多个线程到达屏障点
* - Semaphore:信号量,控制并发访问数量
* - Exchanger:线程间交换数据
* - CompletableFuture:异步编程
*/
public class ConcurrencyTools {
// CountDownLatch示例:等待所有线程完成
public static void countDownLatchDemo() throws InterruptedException {
int threadCount = 5;
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 开始工作");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 完成工作");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown(); // 计数器减1
}
}).start();
}
latch.await(); // 等待计数器归零
System.out.println("所有线程已完成,继续执行");
}
// CyclicBarrier示例:等待所有线程到达屏障点
public static void cyclicBarrierDemo() {
int parties = 3;
CyclicBarrier barrier = new CyclicBarrier(parties, () -> {
System.out.println("所有线程已到达屏障点,执行汇总操作");
});
for (int i = 0; i < parties; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 到达屏障");
barrier.await();
System.out.println(Thread.currentThread().getName() + " 继续执行");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
// Semaphore示例:限流
public static void semaphoreDemo() {
Semaphore semaphore = new Semaphore(3); // 最多3个并发
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // 获取许可
System.out.println(Thread.currentThread().getName() + " 获取许可,执行业务");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放许可
System.out.println(Thread.currentThread().getName() + " 释放许可");
}
}).start();
}
}
// CompletableFuture示例:异步编程
public static void completableFutureDemo() {
// 异步执行任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
return "Hello";
} catch (InterruptedException e) {
return "Error";
}
}).thenApply(result -> result + " World") // 转换结果
.thenApply(String::toUpperCase)
.exceptionally(throwable -> "Exception: " + throwable.getMessage());
// 组合多个异步任务
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
CompletableFuture<String> combined = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
// 等待结果
try {
System.out.println(future.get());
System.out.println(combined.get());
} catch (Exception e) {
e.printStackTrace();
}
}
// BlockingQueue示例:生产者-消费者模式
public static void blockingQueueDemo() {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
// 生产者
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 100; i++) {
queue.put(i); // 队列满时阻塞
System.out.println("生产: " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// 消费者
Thread consumer = new Thread(() -> {
try {
while (true) {
Integer value = queue.take(); // 队列空时阻塞
System.out.println("消费: " + value);
Thread.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
producer.start();
consumer.start();
}
}
三、网络编程与NIO
3.1 BIO与NIO对比
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
/**
* BIO(Blocking I/O):阻塞IO,每个连接一个线程
* NIO(Non-blocking I/O):非阻塞IO,单线程处理多个连接
* AIO(Asynchronous I/O):异步IO,回调机制
*/
public class NetworkProgramming {
// BIO服务器示例
public static class BIOServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("BIO服务器启动,端口8080");
while (true) {
// 阻塞等待客户端连接
Socket socket = serverSocket.accept();
System.out.println("客户端连接:" + socket.getRemoteSocketAddress());
// 每个连接创建新线程处理
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true)) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("收到: " + line);
writer.println("ECHO: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
}
}
// NIO服务器示例(Selector多路复用)
public static class NIOServer {
public static void main(String[] args) throws IOException {
// 创建Selector
Selector selector = Selector.open();
// 创建ServerSocketChannel并注册到Selector
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.bind(new InetSocketAddress(8081));
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO服务器启动,端口8081");
// 事件循环
while (true) {
selector.select(); // 阻塞等待事件
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isAcceptable()) {
// 接受新连接
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client = server.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
System.out.println("客户端连接:" + client.getRemoteAddress());
} else if (key.isReadable()) {
// 读取数据
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = client.read(buffer);
if (bytesRead > 0) {
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
String message = new String(data);
System.out.println("收到: " + message);
// 响应
ByteBuffer response = ByteBuffer.wrap(("ECHO: " + message).getBytes());
client.write(response);
} else if (bytesRead == -1) {
client.close();
System.out.println("客户端断开连接");
}
}
}
}
}
}
// 零拷贝示例(transferTo)
public static void zeroCopyDemo() throws IOException {
// 传统方式:数据需要从内核空间复制到用户空间,再写回内核空间
// 零拷贝:直接在内核空间传输,减少拷贝次数
FileChannel source = FileChannel.open(Paths.get("source.txt"), StandardOpenOption.READ);
FileChannel dest = FileChannel.open(Paths.get("dest.txt"),
StandardOpenOption.CREATE, StandardOpenOption.WRITE);
// 零拷贝传输
long transferred = source.transferTo(0, source.size(), dest);
System.out.println("传输字节数:" + transferred);
source.close();
dest.close();
}
}