CloseableHttpClient未设置Socket超时导致线程池堵塞

在使用CompletableFuture与CloseableHttpClient进行多线程下载时,遇到因Socket超时未设置导致线程池堵塞的问题。通过jstack分析发现ForkJoinPool线程阻塞在SocketInputStream的socketRead0方法。解决方案是设定Socket超时时间,并确保使用完CloseableHttpClient后正确关闭资源,避免线程池阻塞。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

线上使用 CompletableFuture.supplyAsync  来多线程下载影像,使用了默认的ForkJoinPool线程池。

项目运行一段时间后下载影像方法全部报错:

java.util.concurrent.TimeoutException

下载方法如下:

CloseableHttpClient http = HttpClientBuilder.create().build();

public File download(String url, String filename) throws IOException {
    File file = new File(parent, filename);
    try (FileOutputStream fos = new FileOutputStream(file);
         CloseableHttpResponse response = http.execute(new HttpGet(url));) {
        int sc = response.getStatusLine().getStatusCode();
        if (sc == HttpStatus.SC_OK) {
            HttpEntity entity = response.getEntity();
            entity.writeTo(fos);
        } else {
            ...
        }
    }
    return file;
}

 

排查代码发现出现在 CompletableFuture.get() 步骤超时

CompletableFuture<List<File>> sequence = sequence(
        imgs.stream().map(p -> CompletableFuture.supplyAsync(() -> {
            ...
        }).exceptionally(e -> {
            ...
        })).collect(toList()));
try {
    return sequence.get(300L, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
    ...
}

考虑到当影像量庞大时候下载速度问题,超时时间设置为5分钟之久。

这么久的超时时间设置,每次方法调用出现都出现TimeoutException问题,猜测是线程堵塞。

 

项目部署在docker容器,进入bash 。

jps -l // 获取项目进程ID

 

 由于使用了CompletableFuture 异步操作的默认线程池ForkJoinPool 

 使用jstack 获取项目堆栈日志。

jstack 1(项目进程ID) | grep ForkJoinPool -A 10

 获取到的日志部分如下所示。

"ForkJoinPool.commonPool-worker-1" #521 daemon prio=5 os_prio=0 tid=0x00007f4b901be800 nid=0x20e runnable [0x00007f4b5b693000]                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                               
   java.lang.Thread.State: RUNNABLE                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                               
        at java.net.SocketInputStream.socketRead0(Native Method)                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值