大家好!今天给大家分享一个 Java Socket + 线程池 实现的高性能文件上传服务器,支持 多客户端并发上传,代码可直接运行,适合 面试、项目实战、性能优化 学习!
📌 本文亮点:
✅ 完整可运行代码(附详细注释)
✅ 线程池优化(拒绝策略、队列控制)
✅ UUID 生成唯一文件名(避免冲突)
✅ 客户端/服务器完整交互流程
✅ 适合新手进阶 & 面试加分项
如果你对 Java网络编程、高并发、线程池 感兴趣,这篇一定要看!👇
🚀 1. 项目背景
在实际开发中,我们经常需要实现 文件上传 功能,比如:
用户上传头像
日志文件收集
分布式系统数据传输
如果直接用 单线程 Socket,服务器只能 一个一个处理请求,性能极差!
💡 解决方案:
✅ 多线程:每个客户端连接分配一个线程
✅ 线程池:避免频繁创建/销毁线程,提升性能
✅ 非阻塞IO(NIO):更高性能(本文先讲基础版)
💻 2. 代码实现
📌 服务器端(支持多客户端并发上传)
import java.io.*;
import java.net.*;
import java.util.UUID;
import java.util.concurrent.*;
public class FileUploadServer {
public static void main(String[] args) throws IOException {
// 创建线程池(核心3线程,最大16线程,队列容量2,60秒空闲回收)
ThreadPoolExecutor pool = new ThreadPoolExecutor(
3, 16, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy() // 队列满时拒绝新任务
);
ServerSocket server = new ServerSocket(10086);
System.out.println("⚡服务器启动,等待客户端连接...");
while (true) {
Socket socket = server.accept(); // 阻塞等待客户端连接
pool.submit(new FileUploadHandler(socket)); // 提交任务到线程池
System.out.println("🔗 客户端连接: " + socket.getInetAddress());
}
}
}
class FileUploadHandler implements Runnable {
private final Socket socket;
public FileUploadHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
) {
// 生成唯一文件名(避免冲突)
String fileName = UUID.randomUUID() + ".jpg";
// 写入本地文件
try (FileOutputStream fos = new FileOutputStream(fileName)) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("📁 文件保存成功: " + fileName);
}
// 返回响应给客户端
os.write("✅ 上传成功!".getBytes());
os.flush();
} catch (IOException e) {
System.err.println("❌ 处理异常: " + e.getMessage());
} finally {
try {
socket.close(); // 关闭连接
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
📌 客户端(上传文件)
import java.io.*;
import java.net.*;
public class FileUploadClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 10086); // 连接服务器
System.out.println("🚀 连接服务器成功!");
// 读取本地文件并发送
try (
FileInputStream fis = new FileInputStream("test.jpg");
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
) {
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
System.out.println("📤 文件发送完成!");
// 接收服务器响应
byte[] response = new byte[1024];
int responseLen = is.read(response);
System.out.println("📥 服务器响应: " + new String(response, 0, responseLen));
} finally {
socket.close();
}
}
}
📊 3. 关键优化点
✅ 1. 线程池管理
核心线程数 = 3(保持活跃)
最大线程数 = 16(应对突发流量)
队列容量 = 2(防止资源耗尽)
拒绝策略 = AbortPolicy(队列满时直接拒绝)
✅ 2. 唯一文件名生成
String fileName = UUID.randomUUID() + ".jpg"; // 避免文件名冲突
✅ 3. 资源自动关闭
使用 try-with-resources,确保 Socket
、FileOutputStream
等资源自动释放,避免内存泄漏!
🚀 4. 如何运行?
启动服务器:
java FileUploadServer
启动客户端(可开多个):
java FileUploadClient
查看结果:
服务器控制台显示客户端连接和文件保存路径
客户端收到
上传成功
响应
💡 5. 扩展优化
NIO(Non-blocking IO):更高性能(Netty 底层实现)
断点续传:记录文件偏移量
加密传输:SSL/TLS 安全传输
分布式存储:上传到云存储(OSS)
📌 6. 总结
本文实现了一个高并发文件上传服务器,适合 面试、项目实战
关键点:线程池、Socket、资源管理、UUID 文件名
优化方向:NIO、断点续传、加密传输
如果觉得有用,点赞 👍 + 关注 ➕,后续更新更多 Java 高并发实战!
📢 互动话题:
你在项目中遇到过文件上传的问题吗?欢迎评论区讨论!👇
#Java #Socket #多线程 #高并发 #文件上传 #面试必备
public class MyRunable implements Runnable{
Socket socket;
public MyRunable(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
// 接收文件
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String name = UUID.randomUUID().toString().replace("-", "");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(name + ".jpg"));
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.flush();
bos.close(); // 关闭文件输出流
// 发送响应给客户端
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();
// 先关闭输出流,再关闭socket
socket.shutdownOutput();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}}
public class reserve {
public static void main(String[] args) throws IOException {
ThreadPoolExecutor pool=new ThreadPoolExecutor(
3,//核心线程数量
16,//线程池总大小
60,//空闲时间
TimeUnit.SECONDS,//空闲时间单位
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工场,让线程池如何创建对象
new ThreadPoolExecutor.AbortPolicy()//阻塞队列
);
ServerSocket ss = new ServerSocket(10086);
while (true) {
Socket socket = ss.accept();
pool.submit(new MyRunable(socket));
}
}
}
public class Main {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.129.132", 10086);
// 发送文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("微信图片_20250303192811.jpg"));
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.flush();
socket.shutdownOutput(); // 告诉服务器数据发送完毕
// 接收服务器响应
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String response = br.readLine();
System.out.println("服务器响应: " + response);
// 关闭资源
bis.close();
br.close();
socket.close();
}
}