Java问题:使用线程池并发发送多文件时出错
嘿,我来帮你捋捋这个并发文件上传代码里可能踩的坑,结合你给出的代码片段,咱们一步步排查问题:
资源未正确关闭,导致连接/文件句柄泄漏
从你的代码片段看,你创建了OutputStream out和FileInputStream in,但没看到关闭资源的逻辑。在并发场景下,这些资源如果不及时释放,很快会耗尽系统的连接池或者文件句柄,导致后续请求失败。推荐用Java的try-with-resources语法自动关闭资源,不用手动写finally:
try (FileInputStream in = new FileInputStream(file); OutputStream out = connection.getOutputStream()) { // 这里写文件内容写入输出流的逻辑 } catch (IOException e) { // 异常处理,比如打印日志 }HttpURLConnection默认并发连接数限制
JDK默认给HttpURLConnection设置了每个主机最多2个并发连接的限制,如果你的并发上传线程数超过这个数,会导致请求阻塞在连接建立阶段。可以通过系统属性调整这个限制:
// 在应用启动时设置,比如main方法里 System.setProperty("http.maxConnections", "15"); // 根据你的并发需求调整数值同时记得给连接设置超时时间,避免线程长时间挂起:
connection.setConnectTimeout(5000); // 连接超时5秒 connection.setReadTimeout(10000); // 读取响应超时10秒请求头配置不完整(文件上传必备)
上传文件需要正确设置请求方法和Content-Type,你提到的“setting request properties here”可能漏了关键配置:connection.setRequestMethod("POST"); connection.setDoOutput(true); // 允许写入输出流 connection.setDoInput(true); // 允许读取响应 // 如果是multipart/form-data格式的上传(最常见的文件上传方式) String boundary = "----CustomBoundary" + System.currentTimeMillis(); connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);文件内容写入逻辑缺失
你的代码片段写到FileInputStream in = n...就断了,大概率是没实现文件内容写入输出流的逻辑。需要循环读取文件字节并写入:byte[] buffer = new byte[4096]; // 4KB缓冲区,平衡性能和内存占用 int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } out.flush(); // 确保所有数据都发送出去异常处理不到位
并发场景下,单个线程的未捕获异常会导致线程直接终止,还可能影响整个线程池的稳定性。一定要在run()方法里捕获所有异常并处理:@Override public void run() { HttpURLConnection connection = null; try { // 初始化连接、设置属性、写入文件的逻辑 } catch (IOException e) { // 用日志框架记录详细错误(比如SLF4J),别只打个错误信息 System.err.println("上传文件[" + file.getName() + "]失败: " + e.getMessage()); e.printStackTrace(); } finally { // 如果不用try-with-resources,这里手动断开连接 if (connection != null) { connection.disconnect(); } } }
如果这些点都检查过还是有问题,可以把具体的错误日志贴出来,比如是IOException的具体信息,或者连接超时的提示,这样能更精准定位问题~
内容的提问来源于stack exchange,提问作者DrunkOnBytes

