🚀 第二阶段:Java进阶技能②Java I/O与网络编程
💡 学习目标:掌握Java I/O流体系、文件操作、网络编程基础和多线程编程,构建高效的数据处理和网络通信应用
📁 Java I/O流体系
🎯 I/O流概述
🌟 I/O流:Java中处理输入输出的核心机制,用于在程序与外部数据源之间传输数据
✨ I/O流分类体系
📊 Java I/O流分类
│
├── 🔄 按数据流向分类
│ ├── 📥 输入流 (InputStream/Reader)
│ └── 📤 输出流 (OutputStream/Writer)
│
├── 🔢 按数据类型分类
│ ├── 📋 字节流 (Byte Stream)
│ │ ├── InputStream/OutputStream
│ │ └── 处理二进制数据
│ └── 📝 字符流 (Character Stream)
│ ├── Reader/Writer
│ └── 处理文本数据
│
└── 🎯 按功能分类
├── 🔗 节点流 (Node Stream)
│ └── 直接连接数据源
└── 🔧 处理流 (Processing Stream)
└── 包装其他流,提供额外功能
🏗️ 核心流类层次结构
📋 字节流家族
// 输入流
InputStream (抽象基类)
├── FileInputStream // 文件输入流
├── ByteArrayInputStream // 字节数组输入流
├── BufferedInputStream // 缓冲输入流
└── ObjectInputStream // 对象输入流
// 输出流
OutputStream (抽象基类)
├── FileOutputStream // 文件输出流
├── ByteArrayOutputStream// 字节数组输出流
├── BufferedOutputStream // 缓冲输出流
└── ObjectOutputStream // 对象输出流
📝 字符流家族
// 输入流
Reader (抽象基类)
├── FileReader // 文件字符输入流
├── StringReader // 字符串输入流
├── BufferedReader // 缓冲字符输入流
└── InputStreamReader // 字节流到字符流转换
// 输出流
Writer (抽象基类)
├── FileWriter // 文件字符输出流
├── StringWriter // 字符串输出流
├── BufferedWriter // 缓冲字符输出流
└── OutputStreamWriter // 字符流到字节流转换
💻 基础I/O操作实战
📝 文件读写基础示例
🎯 示例1:基础文件读写
import java.io.*;
public class BasicFileIO {
// 字节流文件复制
public static void copyFileWithBytes(String source, String target) {
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(target)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
System.out.println("文件复制完成!");
} catch (IOException e) {
System.err.println("文件操作失败: " + e.getMessage());
}
}
// 字符流文本处理
public static void processTextFile(String filename) {
try (BufferedReader reader = new BufferedReader(new FileReader(filename));
BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
String line;
int lineNumber = 1;
while ((line = reader.readLine()) != null) {
// 添加行号
writer.write(lineNumber + ": " + line);
writer.newLine();
lineNumber++;
}
System.out.println("文本处理完成!");
} catch (IOException e) {
System.err.println("文本处理失败: " + e.getMessage());
}
}
public static void main(String[] args) {
// 测试文件操作
copyFileWithBytes("input.txt", "copy.txt");
processTextFile("input.txt");
}
}
🔧 缓冲流性能优化
🚀 性能对比示例
import java.io.*;
import java.time.LocalDateTime;
public class BufferedStreamDemo {
// 不使用缓冲流
public static long copyWithoutBuffer(String source, String target) {
long startTime = System.currentTimeMillis();
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(target)) {
int data;
while ((data = fis.read()) != -1) {
fos.write(data);
}
} catch (IOException e) {
e.printStackTrace();
}
return System.currentTimeMillis() - startTime;
}
// 使用缓冲流
public static long copyWithBuffer(String source, String target) {
long startTime = System.currentTimeMillis();
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(target))) {
int data;
while ((data = bis.read()) != -1) {
bos.write(data);
}
} catch (IOException e) {
e.printStackTrace();
}
return System.currentTimeMillis() - startTime;
}
public static void main(String[] args) {
String sourceFile = "large-file.txt";
long timeWithoutBuffer = copyWithoutBuffer(sourceFile, "copy1.txt");
long timeWithBuffer = copyWithBuffer(sourceFile, "copy2.txt");
System.out.println("不使用缓冲流耗时: " + timeWithoutBuffer + "ms");
System.out.println("使用缓冲流耗时: " + timeWithBuffer + "ms");
System.out.println("性能提升: " + (timeWithoutBuffer / (double) timeWithBuffer) + "倍");
}
}
🎯 对象序列化
📦 序列化基础概念
🔍 序列化:将对象转换为字节序列的过程,用于对象的持久化存储或网络传输
🎯 序列化应用场景
- 💾 对象持久化存储
- 🌐 网络数据传输
- 🔄 分布式系统通信
- 💿 缓存系统实现
- 📋 深拷贝对象
⚠️ 序列化注意事项
- 类必须实现
Serializable接口 transient关键字标记不序列化字段serialVersionUID控制版本兼容性- 静态字段不会被序列化
- 父类序列化影响子类
💻 序列化实战示例
🎯 示例2:完整序列化演示
import java.io.*;
import java.util.*;
// 可序列化的用户类
class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String password; // 不序列化密码
private List<String> hobbies;
public User(String name, int age, String password) {
this.name = name;
this.age = age;
this.password = password;
this.hobbies = new ArrayList<>();
}
// getter和setter方法
public void addHobby(String hobby) {
hobbies.add(hobby);
}
@Override
public String toString() {
return String.format("User{name='%s', age=%d, password='%s', hobbies=%s}",
name, age, password, hobbies);
}
}
public class SerializationDemo {
// 序列化对象
public static void serializeUser(User user, String filename) {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(filename))) {
oos.writeObject(user);
System.out.println("用户对象序列化完成: " + filename);
} catch (IOException e) {
System.err.println("序列化失败: " + e.getMessage());
}
}
// 反序列化对象
public static User deserializeUser(String filename) {
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(filename))) {
User user = (User) ois.readObject();
System.out.println("用户对象反序列化完成");
return user;
} catch (IOException | ClassNotFoundException e) {
System.err.println("反序列化失败: " + e.getMessage());
return null;
}
}
public static void main(String[] args) {
// 创建用户对象
User user = new User("张三", 25, "secret123");
user.addHobby("编程");
user.addHobby("阅读");
System.out.println("原始对象: " + user);
// 序列化
serializeUser(user, "user.ser");
// 反序列化
User deserializedUser = deserializeUser("user.ser");
System.out.println("反序列化对象: " + deserializedUser);
// 注意:password字段为null,因为被transient修饰
}
}
📂 文件操作与NIO
🎯 传统I/O vs NIO
📊 对比分析
| 特性 | 传统I/O (BIO) | NIO (New I/O) |
|---|---|---|
| 🔄 I/O模型 | 阻塞式 | 非阻塞式 |
| 📊 数据处理 | 面向流 | 面向缓冲区 |
| 🎯 选择器 | 不支持 | 支持Selector |
| 🧵 线程模型 | 一线程一连接 | 一线程多连接 |
| 📈 性能 | 适合连接数少 | 适合连接数多 |
| 🔧 复杂度 | 简单 | 相对复杂 |
💻 NIO核心组件
🔧 Channel、Buffer、Selector
📋 NIO三大核心组件
-
📡 Channel(通道)
- 双向数据传输通道
- 类似传统I/O的流,但支持读写
- 主要实现:FileChannel、SocketChannel、ServerSocketChannel
-
📦 Buffer(缓冲区)
- 数据容器,所有数据通过Buffer处理
- 核心属性:capacity、position、limit、mark
- 主要类型:ByteBuffer、CharBuffer、IntBuffer等
-
🎯 Selector(选择器)
- 单线程管理多个Channel
- 事件驱动模型
- 提高并发处理能力
💻 NIO文件操作实战
🎯 示例3:NIO文件操作
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class NIOFileDemo {
// 使用NIO复制文件
public static void copyFileWithNIO(String source, String target) {
try (FileChannel sourceChannel = FileChannel.open(Paths.get(source),
StandardOpenOption.READ);
FileChannel targetChannel = FileChannel.open(Paths.get(target),
StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (sourceChannel.read(buffer) > 0) {
buffer.flip(); // 切换到读模式
targetChannel.write(buffer);
buffer.clear(); // 清空缓冲区
}
System.out.println("NIO文件复制完成!");
} catch (IOException e) {
System.err.println("NIO文件操作失败: " + e.getMessage());
}
}
// 使用Files工具类
public static void filesUtilDemo() {
try {
Path path = Paths.get("demo.txt");
// 写入文件
List<String> lines = List.of(
"第一行内容",
"第二行内容",
"第三行内容"
);
Files.write(path, lines, StandardCharsets.UTF_8);
// 读取文件
List<String> readLines = Files.readAllLines(path, StandardCharsets.UTF_8);
System.out.println("文件内容:");
readLines.forEach(System.out::println);
// 文件信息
System.out.println("文件大小: " + Files.size(path) + " bytes");
System.out.println("是否存在: " + Files.exists(path));
System.out.println("是否可读: " + Files.isReadable(path));
} catch (IOException e) {
System.err.println("Files操作失败: " + e.getMessage());
}
}
public static void main(String[] args) {
copyFileWithNIO("input.txt", "nio-copy.txt");
filesUtilDemo();
}
}
🗂️ 目录遍历与文件监控
📁 目录操作实战
🎯 示例4:目录遍历与文件监控
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
public class DirectoryOperations {
// 递归遍历目录
public static void walkDirectory(String dirPath) {
try {
Files.walkFileTree(Paths.get(dirPath), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println("文件: " + file.getFileName() +
" (大小: " + attrs.size() + " bytes)");
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
System.out.println("进入目录: " + dir.getFileName());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
System.out.println("离开目录: " + dir.getFileName());
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
System.err.println("目录遍历失败: " + e.getMessage());
}
}
// 文件监控
public static void watchDirectory(String dirPath) {
try {
WatchService watchService = FileSystems.getDefault().newWatchService();
Path path = Paths.get(dirPath);
path.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
System.out.println("开始监控目录: " + dirPath);
while (true) {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
Path fileName = (Path) event.context();
System.out.println("检测到变化: " + kind.name() + " - " + fileName);
}
if (!key.reset()) {
break;
}
}
} catch (IOException | InterruptedException e) {
System.err.println("文件监控失败: " + e.getMessage());
}
}
public static void main(String[] args) {
// 遍历当前目录
walkDirectory(".");
// 监控当前目录(这会阻塞程序)
// watchDirectory(".");
}
}
🌐 网络编程基础
🎯 网络编程概述
🌍 网络通信基础
🔗 网络编程核心概念
🌐 网络通信模型
│
├── 📡 TCP/IP协议栈
│ ├── 应用层 (HTTP, FTP, SMTP)
│ ├── 传输层 (TCP, UDP)
│ ├── 网络层 (IP)
│ └── 数据链路层 (Ethernet)
│
├── 🔌 Socket编程
│ ├── TCP Socket (可靠连接)
│ └── UDP Socket (无连接)
│
└── 🎯 Java网络API
├── Socket/ServerSocket (TCP)
├── DatagramSocket (UDP)
└── NIO SocketChannel
💻 TCP Socket编程
🔗 客户端-服务器通信
🎯 示例5:TCP聊天程序
// TCP服务器
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
public class TCPServer {
private static final int PORT = 8888;
private ExecutorService threadPool;
public TCPServer() {
threadPool = Executors.newFixedThreadPool(10);
}
public void start() {
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("服务器启动,监听端口: " + PORT);
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("新客户端连接: " + clientSocket.getInetAddress());
// 为每个客户端创建处理线程
threadPool.submit(new ClientHandler(clientSocket));
}
} catch (IOException e) {
System.err.println("服务器启动失败: " + e.getMessage());
}
}
// 客户端处理器
private static class ClientHandler implements Runnable {
private Socket socket;
private BufferedReader reader;
private PrintWriter writer;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new PrintWriter(socket.getOutputStream(), true);
writer.println("欢迎连接到聊天服务器!");
String message;
while ((message = reader.readLine()) != null) {
System.out.println("收到消息: " + message);
if ("bye".equalsIgnoreCase(message)) {
writer.println("再见!");
break;
}
// 回显消息
writer.println("服务器回复: " + message);
}
} catch (IOException e) {
System.err.println("客户端处理异常: " + e.getMessage());
} finally {
closeConnection();
}
}
private void closeConnection() {
try {
if (reader != null) reader.close();
if (writer != null) writer.close();
if (socket != null) socket.close();
System.out.println("客户端连接已关闭");
} catch (IOException e) {
System.err.println("关闭连接异常: " + e.getMessage());
}
}
}
public static void main(String[] args) {
new TCPServer().start();
}
}
// TCP客户端
public class TCPClient {
private static final String SERVER_HOST = "localhost";
private static final int SERVER_PORT = 8888;
public void connect() {
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in))) {
System.out.println("连接到服务器成功!");
// 启动接收消息线程
Thread receiveThread = new Thread(() -> {
try {
String serverMessage;
while ((serverMessage = reader.readLine()) != null) {
System.out.println(serverMessage);
}
} catch (IOException e) {
System.err.println("接收消息异常: " + e.getMessage());
}
});
receiveThread.start();
// 发送消息
System.out.println("请输入消息 (输入'bye'退出):");
String userInput;
while ((userInput = consoleReader.readLine()) != null) {
writer.println(userInput);
if ("bye".equalsIgnoreCase(userInput)) {
break;
}
}
} catch (IOException e) {
System.err.println("客户端连接失败: " + e.getMessage());
}
}
public static void main(String[] args) {
new TCPClient().connect();
}
}
📡 UDP Socket编程
🚀 无连接通信
🎯 示例6:UDP通信程序
// UDP服务器
import java.net.*;
import java.io.*;
public class UDPServer {
private static final int PORT = 9999;
private DatagramSocket socket;
public void start() {
try {
socket = new DatagramSocket(PORT);
System.out.println("UDP服务器启动,监听端口: " + PORT);
byte[] buffer = new byte[1024];
while (true) {
// 接收数据包
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String message = new String(packet.getData(), 0, packet.getLength());
System.out.println("收到来自 " + packet.getAddress() + " 的消息: " + message);
// 发送回复
String reply = "服务器收到: " + message;
byte[] replyData = reply.getBytes();
DatagramPacket replyPacket = new DatagramPacket(
replyData, replyData.length, packet.getAddress(), packet.getPort());
socket.send(replyPacket);
}
} catch (IOException e) {
System.err.println("UDP服务器异常: " + e.getMessage());
} finally {
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
}
public static void main(String[] args) {
new UDPServer().start();
}
}
// UDP客户端
public class UDPClient {
private static final String SERVER_HOST = "localhost";
private static final int SERVER_PORT = 9999;
public void sendMessage(String message) {
try (DatagramSocket socket = new DatagramSocket()) {
// 发送数据
byte[] data = message.getBytes();
InetAddress address = InetAddress.getByName(SERVER_HOST);
DatagramPacket packet = new DatagramPacket(data, data.length, address, SERVER_PORT);
socket.send(packet);
// 接收回复
byte[] buffer = new byte[1024];
DatagramPacket replyPacket = new DatagramPacket(buffer, buffer.length);
socket.receive(replyPacket);
String reply = new String(replyPacket.getData(), 0, replyPacket.getLength());
System.out.println("服务器回复: " + reply);
} catch (IOException e) {
System.err.println("UDP客户端异常: " + e.getMessage());
}
}
public static void main(String[] args) {
UDPClient client = new UDPClient();
// 发送多条消息
client.sendMessage("Hello UDP Server!");
client.sendMessage("这是第二条消息");
client.sendMessage("UDP通信测试完成");
}
}
🧵 多线程编程
🎯 线程基础概念
🔄 进程与线程
🎯 进程 vs 线程对比
| 特性 | 进程 (Process) | 线程 (Thread) |
|---|---|---|
| 🏠 内存空间 | 独立内存空间 | 共享进程内存 |
| 🔄 创建开销 | 较大 | 较小 |
| 📡 通信方式 | IPC机制 | 共享内存 |
| 🛡️ 安全性 | 相互隔离 | 需要同步 |
| 💥 崩溃影响 | 不影响其他进程 | 可能影响整个进程 |
🧵 Java线程状态
📊 线程生命周期
│
NEW ──────▶ RUNNABLE ◀──▶ BLOCKED
│ ▲ │
▼ │ ▼
WAITING │ TIMED_WAITING
│ │ │
▼ │ ▼
TERMINATED ◀────────┘
💻 线程创建与管理
🚀 三种创建线程的方式
🎯 示例7:线程创建方式对比
import java.util.concurrent.*;
// 方式1:继承Thread类
class MyThread extends Thread {
private String threadName;
public MyThread(String name) {
this.threadName = name;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(threadName + " - 计数: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(threadName + " 被中断");
return;
}
}
System.out.println(threadName + " 执行完成");
}
}
// 方式2:实现Runnable接口
class MyRunnable implements Runnable {
private String taskName;
public MyRunnable(String name) {
this.taskName = name;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(taskName + " - 执行: " + i);
try {
Thread.sleep(800);
} catch (InterruptedException e) {
System.out.println(taskName + " 被中断");
return;
}
}
System.out.println(taskName + " 任务完成");
}
}
// 方式3:实现Callable接口
class MyCallable implements Callable<String> {
private String taskName;
private int computeTime;
public MyCallable(String name, int time) {
this.taskName = name;
this.computeTime = time;
}
@Override
public String call() throws Exception {
System.out.println(taskName + " 开始计算...");
int sum = 0;
for (int i = 1; i <= computeTime; i++) {
sum += i;
Thread.sleep(100); // 模拟计算时间
}
String result = taskName + " 计算结果: " + sum;
System.out.println(result);
return result;
}
}
public class ThreadCreationDemo {
public static void main(String[] args) {
System.out.println("=== 线程创建方式演示 ===");
// 方式1:继承Thread
System.out.println("\n1. 继承Thread类:");
MyThread thread1 = new MyThread("Thread-1");
MyThread thread2 = new MyThread("Thread-2");
thread1.start();
thread2.start();
// 等待Thread方式的线程完成
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 方式2:实现Runnable
System.out.println("\n2. 实现Runnable接口:");
Thread runnableThread1 = new Thread(new MyRunnable("Runnable-1"));
Thread runnableThread2 = new Thread(new MyRunnable("Runnable-2"));
runnableThread1.start();
runnableThread2.start();
// 等待Runnable方式的线程完成
try {
runnableThread1.join();
runnableThread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 方式3:使用Callable和Future
System.out.println("\n3. 实现Callable接口:");
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future1 = executor.submit(new MyCallable("Callable-1", 10));
Future<String> future2 = executor.submit(new MyCallable("Callable-2", 15));
try {
// 获取计算结果
String result1 = future1.get(); // 阻塞等待结果
String result2 = future2.get();
System.out.println("获取到结果1: " + result1);
System.out.println("获取到结果2: " + result2);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
System.out.println("\n所有线程执行完成!");
}
}
🔒 线程同步与安全
⚠️ 线程安全问题
🚨 常见线程安全问题
- 🔄 竞态条件:多线程同时访问共享资源
- 💥 数据不一致:读写操作不原子化
- 🔒 死锁:线程相互等待资源
- 🌀 活锁:线程不断重试但无法进展
- 😴 饥饿:线程长期无法获得资源
🛡️ 同步机制实战
🎯 示例8:线程同步解决方案
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.AtomicInteger;
// 银行账户类 - 演示线程安全
class BankAccount {
private double balance;
private final ReentrantLock lock = new ReentrantLock();
public BankAccount(double initialBalance) {
this.balance = initialBalance;
}
// 使用synchronized关键字
public synchronized void depositSync(double amount) {
if (amount > 0) {
balance += amount;
System.out.println(Thread.currentThread().getName() +
" 存款: " + amount + ", 余额: " + balance);
}
}
// 使用ReentrantLock
public void depositLock(double amount) {
lock.lock();
try {
if (amount > 0) {
balance += amount;
System.out.println(Thread.currentThread().getName() +
" 存款: " + amount + ", 余额: " + balance);
}
} finally {
lock.unlock();
}
}
// 不安全的取款方法(演示问题)
public void withdrawUnsafe(double amount) {
if (balance >= amount) {
// 模拟处理时间
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
balance -= amount;
System.out.println(Thread.currentThread().getName() +
" 取款: " + amount + ", 余额: " + balance);
} else {
System.out.println(Thread.currentThread().getName() +
" 取款失败,余额不足: " + balance);
}
}
// 安全的取款方法
public synchronized void withdrawSafe(double amount) {
if (balance >= amount) {
balance -= amount;
System.out.println(Thread.currentThread().getName() +
" 取款: " + amount + ", 余额: " + balance);
} else {
System.out.println(Thread.currentThread().getName() +
" 取款失败,余额不足: " + balance);
}
}
public synchronized double getBalance() {
return balance;
}
}
// 生产者-消费者模式
class ProducerConsumerDemo {
private final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
private final AtomicInteger counter = new AtomicInteger(0);
// 生产者
class Producer implements Runnable {
@Override
public void run() {
try {
for (int i = 0; i < 20; i++) {
int item = counter.incrementAndGet();
queue.put(item);
System.out.println("生产者生产: " + item + ", 队列大小: " + queue.size());
Thread.sleep(100);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
// 消费者
class Consumer implements Runnable {
private String name;
public Consumer(String name) {
this.name = name;
}
@Override
public void run() {
try {
while (true) {
Integer item = queue.take();
System.out.println(name + " 消费: " + item + ", 队列大小: " + queue.size());
Thread.sleep(200);
if (item >= 20) break; // 结束条件
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public void start() {
ExecutorService executor = Executors.newFixedThreadPool(4);
// 启动1个生产者和3个消费者
executor.submit(new Producer());
executor.submit(new Consumer("消费者-1"));
executor.submit(new Consumer("消费者-2"));
executor.submit(new Consumer("消费者-3"));
executor.shutdown();
}
}
public class ThreadSafetyDemo {
public static void main(String[] args) throws InterruptedException {
System.out.println("=== 线程安全演示 ===");
// 1. 银行账户线程安全测试
System.out.println("\n1. 银行账户操作:");
BankAccount account = new BankAccount(1000);
ExecutorService executor = Executors.newFixedThreadPool(5);
// 多线程同时存款
for (int i = 0; i < 5; i++) {
final int amount = (i + 1) * 100;
executor.submit(() -> account.depositSync(amount));
}
// 多线程同时取款
for (int i = 0; i < 3; i++) {
final int amount = 200;
executor.submit(() -> account.withdrawSafe(amount));
}
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
System.out.println("最终余额: " + account.getBalance());
// 2. 生产者-消费者模式
System.out.println("\n2. 生产者-消费者模式:");
ProducerConsumerDemo demo = new ProducerConsumerDemo();
demo.start();
Thread.sleep(10000); // 等待演示完成
System.out.println("\n线程安全演示完成!");
}
}
🔄 并发编程进阶
🎯 线程池技术
🏊♂️ 线程池优势与原理
🎯 线程池核心优势
- 🚀 降低资源消耗:重用已创建的线程
- ⚡ 提高响应速度:任务到达时无需创建线程
- 🎛️ 提高可管理性:统一分配、调优和监控
- 🛡️ 控制并发数:避免系统资源耗尽
📊 Java线程池体系
🏊♂️ Executor框架
│
├── Executor (接口)
├── ExecutorService (接口)
├── AbstractExecutorService (抽象类)
└── ThreadPoolExecutor (核心实现)
├── FixedThreadPool
├── CachedThreadPool
├── SingleThreadExecutor
└── ScheduledThreadPool
💻 线程池实战应用
🎯 示例9:线程池全面应用
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ThreadPoolDemo {
// 自定义线程工厂
static class CustomThreadFactory implements ThreadFactory {
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public CustomThreadFactory(String namePrefix) {
this.namePrefix = namePrefix;
}
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, namePrefix + "-" + threadNumber.getAndIncrement());
thread.setDaemon(false);
return thread;
}
}
// 模拟任务
static class Task implements Runnable {
private final String taskName;
private final int executionTime;
public Task(String taskName, int executionTime) {
this.taskName = taskName;
this.executionTime = executionTime;
}
@Override
public void run() {
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));
System.out.println(String.format("[%s] %s 开始执行任务: %s",
timestamp, Thread.currentThread().getName(), taskName));
try {
Thread.sleep(executionTime * 1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));
System.out.println(String.format("[%s] %s 完成任务: %s",
timestamp, Thread.currentThread().getName(), taskName));
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("=== 线程池应用演示 ===");
// 1. 固定大小线程池
System.out.println("\n1. FixedThreadPool演示:");
ExecutorService fixedPool = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 6; i++) {
fixedPool.submit(new Task("Fixed-Task-" + i, 2));
}
fixedPool.shutdown();
fixedPool.awaitTermination(15, TimeUnit.SECONDS);
// 2. 自定义线程池
System.out.println("\n2. 自定义ThreadPoolExecutor:");
ThreadPoolExecutor customPool = new ThreadPoolExecutor(
2, // 核心线程数
4, // 最大线程数
60L, // 空闲线程存活时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(2), // 工作队列
new CustomThreadFactory("Custom"), // 线程工厂
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 提交任务测试线程池行为
for (int i = 1; i <= 8; i++) {
try {
customPool.submit(new Task("Custom-Task-" + i, 3));
System.out.println("提交任务 " + i + " - 活跃线程: " + customPool.getActiveCount() +
", 队列大小: " + customPool.getQueue().size());
} catch (RejectedExecutionException e) {
System.out.println("任务 " + i + " 被拒绝执行");
}
}
customPool.shutdown();
customPool.awaitTermination(20, TimeUnit.SECONDS);
// 3. 定时任务线程池
System.out.println("\n3. ScheduledThreadPool演示:");
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2);
// 延迟执行
scheduledPool.schedule(() -> {
System.out.println("延迟3秒执行的任务");
}, 3, TimeUnit.SECONDS);
// 固定频率执行
ScheduledFuture<?> periodicTask = scheduledPool.scheduleAtFixedRate(() -> {
System.out.println("每2秒执行一次: " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
}, 1, 2, TimeUnit.SECONDS);
// 10秒后取消定时任务
scheduledPool.schedule(() -> {
periodicTask.cancel(false);
System.out.println("定时任务已取消");
}, 10, TimeUnit.SECONDS);
Thread.sleep(12000);
scheduledPool.shutdown();
System.out.println("\n线程池演示完成!");
}
}
🔒 高级同步工具
🛠️ JUC并发工具类
🎯 示例10:并发工具类应用
import java.util.concurrent.*;
import java.util.Random;
public class ConcurrentUtilsDemo {
// CountDownLatch演示 - 等待多个线程完成
static class CountDownLatchDemo {
public static void demo() throws InterruptedException {
System.out.println("=== CountDownLatch演示 ===");
int workerCount = 5;
CountDownLatch latch = new CountDownLatch(workerCount);
ExecutorService executor = Executors.newFixedThreadPool(workerCount);
// 启动工作线程
for (int i = 1; i <= workerCount; i++) {
final int workerId = i;
executor.submit(() -> {
try {
System.out.println("工作线程 " + workerId + " 开始工作");
Thread.sleep(new Random().nextInt(3000) + 1000);
System.out.println("工作线程 " + workerId + " 完成工作");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
latch.countDown(); // 完成一个任务
}
});
}
System.out.println("主线程等待所有工作完成...");
latch.await(); // 等待所有任务完成
System.out.println("所有工作线程完成,主线程继续执行");
executor.shutdown();
}
}
// CyclicBarrier演示 - 同步屏障
static class CyclicBarrierDemo {
public static void demo() throws InterruptedException {
System.out.println("\n=== CyclicBarrier演示 ===");
int participantCount = 4;
CyclicBarrier barrier = new CyclicBarrier(participantCount, () -> {
System.out.println("🎉 所有参与者都到达屏障,开始下一阶段!");
});
ExecutorService executor = Executors.newFixedThreadPool(participantCount);
for (int i = 1; i <= participantCount; i++) {
final int participantId = i;
executor.submit(() -> {
try {
// 第一阶段工作
System.out.println("参与者 " + participantId + " 完成第一阶段");
Thread.sleep(new Random().nextInt(2000) + 500);
barrier.await(); // 等待其他参与者
// 第二阶段工作
System.out.println("参与者 " + participantId + " 开始第二阶段");
Thread.sleep(new Random().nextInt(1500) + 500);
System.out.println("参与者 " + participantId + " 完成第二阶段");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
}
Thread.sleep(8000);
executor.shutdown();
}
}
// Semaphore演示 - 信号量控制资源访问
static class SemaphoreDemo {
public static void demo() throws InterruptedException {
System.out.println("\n=== Semaphore演示 ===");
// 模拟3个停车位
Semaphore parkingLot = new Semaphore(3);
ExecutorService executor = Executors.newFixedThreadPool(8);
for (int i = 1; i <= 8; i++) {
final int carId = i;
executor.submit(() -> {
try {
System.out.println("汽车 " + carId + " 尝试进入停车场");
parkingLot.acquire(); // 获取停车位
System.out.println("🚗 汽车 " + carId + " 成功停车,剩余车位: " +
parkingLot.availablePermits());
// 停车时间
Thread.sleep(new Random().nextInt(3000) + 1000);
System.out.println("🚙 汽车 " + carId + " 离开停车场");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
parkingLot.release(); // 释放停车位
}
});
}
Thread.sleep(12000);
executor.shutdown();
}
}
public static void main(String[] args) throws InterruptedException {
CountDownLatchDemo.demo();
CyclicBarrierDemo.demo();
SemaphoreDemo.demo();
System.out.println("\n并发工具类演示完成!");
}
}
🎯 综合实战练习
📊 练习1:多线程文件处理器 ⭐⭐⭐⭐
📝 练习描述
设计一个多线程文件处理系统,能够并发处理多个文件,支持不同的处理策略和进度监控。
🎯 学习目标
- 掌握多线程文件I/O操作
- 理解线程池的实际应用
- 学会设计并发安全的系统
- 掌握进度监控和异常处理
📋 具体要求
基础要求:
- 支持多种文件处理操作(复制、压缩、加密等)
- 使用线程池管理工作线程
- 实现处理进度监控
- 提供异常处理和恢复机制
进阶要求:
5. 支持大文件的分块处理
6. 实现处理结果的统计和报告
7. 提供可配置的处理策略
8. 支持处理任务的暂停和恢复
💡 实现提示
public class FileProcessor {
private final ExecutorService threadPool;
private final ConcurrentHashMap<String, ProcessingTask> tasks;
public interface ProcessingStrategy {
void process(Path source, Path target, ProgressCallback callback) throws IOException;
}
public class ProcessingTask {
private final String taskId;
private final Path sourceFile;
private final Path targetFile;
private final ProcessingStrategy strategy;
private volatile ProcessingStatus status;
private final AtomicLong processedBytes;
public Future<ProcessingResult> submit() {
return threadPool.submit(() -> {
// 实现文件处理逻辑
return executeProcessing();
});
}
}
}
🌐 练习2:NIO聊天服务器 ⭐⭐⭐⭐⭐
📝 练习描述
使用Java NIO技术实现一个高性能的聊天服务器,支持多客户端连接、消息广播和私聊功能。
🎯 学习目标
- 掌握NIO非阻塞I/O编程
- 理解Selector多路复用机制
- 学会设计高并发网络应用
- 掌握网络协议设计
📋 具体要求
基础要求:
- 使用NIO实现非阻塞服务器
- 支持多客户端同时连接
- 实现消息广播功能
- 提供用户登录和认证
进阶要求:
5. 支持私聊和群聊功能
6. 实现消息持久化存储
7. 提供在线用户列表
8. 支持文件传输功能
💡 实现提示
public class NIOChatServer {
private Selector selector;
private ServerSocketChannel serverChannel;
private final Map<SocketChannel, User> clients = new ConcurrentHashMap<>();
public void start(int port) throws IOException {
selector = Selector.open();
serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress(port));
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
handleSelectedKeys();
}
}
private void handleSelectedKeys() {
// 处理选择器事件
}
}
🔄 练习3:生产者消费者框架 ⭐⭐⭐⭐
📝 练习描述
设计一个通用的生产者-消费者框架,支持多种队列类型、批量处理和流量控制。
🎯 学习目标
- 深入理解生产者-消费者模式
- 掌握阻塞队列的使用
- 学会设计可扩展的框架
- 理解流量控制机制
📋 具体要求
基础要求:
- 支持多个生产者和消费者
- 提供多种队列实现选择
- 实现优雅的启动和关闭
- 提供监控和统计功能
进阶要求:
5. 支持批量处理模式
6. 实现动态流量控制
7. 提供消息持久化选项
8. 支持消息优先级处理
💡 实现提示
public class ProducerConsumerFramework<T> {
private final BlockingQueue<T> queue;
private final List<Producer<T>> producers;
private final List<Consumer<T>> consumers;
private final ExecutorService executorService;
public static class Builder<T> {
public Builder<T> withQueueType(QueueType type) { return this; }
public Builder<T> withProducerCount(int count) { return this; }
public Builder<T> withConsumerCount(int count) { return this; }
public ProducerConsumerFramework<T> build() { return new ProducerConsumerFramework<>(this); }
}
}
✅ 完成标准
🎯 基础完成标准
- 所有基本功能正常工作
- 代码结构清晰,注释完整
- 异常处理恰当
- 线程安全考虑周全
- 通过基本测试用例
🚀 进阶完成标准
- 性能优化合理
- 支持配置和扩展
- 提供完整的监控信息
- 错误恢复机制完善
- 通过压力测试
🏆 专家级标准
- 设计模式应用恰当
- 代码可维护性高
- 文档和示例完整
- 支持生产环境部署
- 性能达到预期指标
💡 学习建议
🎯 练习顺序
- 先完成基础练习,掌握单个技术点
- 再进行综合练习,学会技术整合
- 最后挑战高级项目,提升系统设计能力
🔍 重点关注
- I/O流:选择合适的流类型,注意资源管理
- NIO:理解非阻塞模型,掌握Buffer和Channel
- 网络编程:协议设计、连接管理、异常处理
- 多线程:线程安全、性能优化、资源竞争
- 并发工具:选择合适的同步机制和并发容器
📝 本章小结
🎯 核心知识点回顾
📁 I/O流体系
- ✅ 掌握字节流和字符流的使用场景
- ✅ 理解缓冲流的性能优化原理
- ✅ 熟练使用对象序列化机制
- ✅ 掌握资源管理和异常处理
📂 NIO技术
- ✅ 理解Channel、Buffer、Selector核心概念
- ✅ 掌握非阻塞I/O编程模型
- ✅ 熟练使用Files工具类
- ✅ 实现文件监控和目录遍历
🌐 网络编程
- ✅ 掌握TCP和UDP Socket编程
- ✅ 理解客户端-服务器通信模式
- ✅ 学会设计网络协议
- ✅ 处理网络异常和连接管理
🧵 多线程编程
- ✅ 掌握三种线程创建方式
- ✅ 理解线程生命周期和状态转换
- ✅ 熟练使用同步机制解决线程安全问题
- ✅ 掌握生产者-消费者模式
🔄 并发编程
- ✅ 熟练使用线程池管理线程资源
- ✅ 掌握JUC并发工具类的应用
- ✅ 理解并发容器和原子类
- ✅ 学会设计高并发系统
📈 学习成果检验
🎯 自我检测清单
- 能够选择合适的I/O流处理不同类型的数据
- 理解NIO与传统I/O的区别和适用场景
- 掌握TCP和UDP网络编程的基本技能
- 能够设计线程安全的多线程程序
- 熟练使用线程池和并发工具类
- 了解各种技术的性能特点和最佳实践
🚀 进阶学习方向
| 方向 | 内容 | 推荐资源 |
|---|---|---|
| 🔧 高性能I/O | Netty框架、零拷贝技术 | Netty官方文档 |
| 🌐 分布式通信 | RPC框架、消息队列 | Dubbo、RocketMQ |
| 🧵 并发编程深入 | JMM、CAS、AQS原理 | 《Java并发编程实战》 |
| 📊 性能调优 | JVM调优、并发性能分析 | JProfiler、VisualVM |
🗺️ 专栏学习路径图
📈 Java程序员从0到1成长路径
🎯 第一阶段:Java基础入门 (4-6周) - ✅ 已完成
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.开发环境 │───▶│ 2.基础语法 │───▶│ 3.面向对象 │───▶│ 4.核心API │
│ 搭建 │ │ │ │ 编程基础 │ │ │
│ ✅ 已完成 │ │ ✅ 已完成 │ │ ✅ 已完成 │ │ ✅ 已完成 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
🚀 第二阶段:Java进阶技能 (4-6周)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.高级特性 │ │ 2.I/O与网络 │ │ 3.新特性 │ │ 4.工具框架 │
│ │ │ 编程 │ │ │ │ 入门 │
│ ✅ 已完成 │ │ ✅ 已完成 │ │ 🎯 下一步 │ │ 📅 计划中 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
🎯 第三阶段:项目实战 (4-8周)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.小型项目 │ │ 2.Web开发 │ │ 3.Spring │ │ 4.数据库与 │
│ 开发 │ │ 基础 │ │ 框架入门 │ │ 持久层 │
│ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
🏆 第四阶段:职业发展 (持续更新)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.代码质量 │ │ 2.开发工具 │ │ 3.面试准备 │ │ 4.职业规划 │
│ 与规范 │ │ 链 │ │ │ │ │
│ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │ │ 📅 计划中 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
📊 第二阶段详细进度
| 章节 | 主要内容 | 预计时间 | 难度 | 状态 |
|---|---|---|---|---|
| 🔧 1.Java高级特性 | 泛型、反射、注解、枚举 | 1-2周 | ⭐⭐⭐⭐ | ✅ 已完成 |
| 📁 2.I/O与网络编程 | 文件操作、网络通信、多线程 | 1-2周 | ⭐⭐⭐⭐ | ✅ 已完成 |
| 🆕 3.Java新特性 | Lambda、Stream API、模块化 | 1周 | ⭐⭐⭐⭐ | 🎯 下一步 |
| 🛠️ 4.工具与框架入门 | Maven/Gradle、JUnit、日志框架 | 1周 | ⭐⭐⭐ | 📅 计划中 |
• 第二阶段进度:50% (2/4章节完成)
• 下一步:学习Java新特性
• 建议:巩固I/O和多线程知识,准备学习现代Java特性
• 重点:掌握Lambda表达式、Stream API和函数式编程
🎬 下一章预告
🆕 第二阶段第3章:Java新特性
🎯 下章学习内容
- 🔗 Lambda表达式与函数式编程
- 🌊 Stream API与数据处理
- 📦 模块化系统(Java 9+)
- ⏰ 新的日期时间API
💡 学习建议
- 理解函数式编程思想
- 掌握Stream API的强大功能
- 学会使用新特性简化代码
- 了解Java版本演进历程
🎉 恭喜完成Java I/O与网络编程的学习!
你已经掌握了Java中重要的I/O处理、网络通信和并发编程技能,
这些技术是构建高性能、高并发应用程序的重要基础!
继续保持学习的热情,向着Java专家的目标前进! 🚀
📧 有问题?欢迎在评论区讨论交流!
⭐ 觉得有用?别忘了点赞收藏!
🔄 继续关注,更多精彩内容即将到来!





