You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法获取Callable类返回值,始终抛出TimeoutException求助

问题解决:连接检查器TimeoutException及Callable返回值获取问题

核心问题分析

  1. Ping命令错误:Linux/OSX分支中使用了带https//的URL,ping是ICMP协议工具,不支持HTTP协议前缀,会导致命令执行失败且进程挂起。
  2. Process流阻塞:未读取子进程的标准输出/错误输出,缓冲区满时会导致进程无法结束,waitFor()一直阻塞,Callable无法返回结果。
  3. Future结果处理错误:原代码未正确接收Callable的返回值,无论get()是否成功都直接设connected=true,逻辑错误。

修正方案

1. 修复ConnectionChecker类

修正ping命令,添加流处理避免阻塞:

public class ConnectionChecker implements Callable<Boolean> {

    @Override
    public Boolean call() throws Exception {
        String cmd;
        // 使用IP地址避免域名解析额外耗时,也可替换为可靠域名如www.baidu.com
        String target = "1.1.1.1";
        
        if (System.getProperty("os.name").startsWith("Windows")) {
            cmd = "ping -n 1 " + target;
        } else {
            cmd = "ping -c 1 " + target;
        }

        Process myProcess = Runtime.getRuntime().exec(cmd);
        
        // 异步读取输出流,避免缓冲区满阻塞进程
        new Thread(() -> {
            try (InputStream in = myProcess.getInputStream()) {
                in.readAllBytes();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
        
        // 异步读取错误流
        new Thread(() -> {
            try (InputStream err = myProcess.getErrorStream()) {
                err.readAllBytes();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        // 等待进程结束并获取退出码
        int exitCode = myProcess.waitFor();
        boolean isConnected = exitCode == 0;
        System.out.println(isConnected);
        return isConnected;
    }
}

2. 修复Updater类的Future结果处理

正确接收Callable返回值,完善异常处理:

public class Updater implements Runnable {
    private final JLabel label;
    private final ExecutorService executor;

    public Updater(JLabel label, ExecutorService executor) {
        this.label = label;
        this.executor = executor;
    }

    public void run() {
        boolean connected = false;
        Callable<Boolean> callable = new ConnectionChecker();
        Future<Boolean> connHandle = executor.submit(callable);
        
        try {
            // 正确获取Callable的返回结果
            connected = connHandle.get(5, TimeUnit.SECONDS);
        } catch (TimeoutException ex) {
            connected = false;
            ex.printStackTrace();
            // 超时后取消未完成的任务
            connHandle.cancel(true);
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
            connected = false;
        } catch (CancellationException | ExecutionException ex) {
            connected = false;
            ex.printStackTrace();
        }

        final boolean result = connected;
        SwingUtilities.invokeLater(() -> {
            label.setText(result ? "online" : "offline");
        });
    }
}

额外优化建议

  • 可以将目标地址(1.1.1.1)作为参数传入ConnectionChecker,增强灵活性。
  • 对于Swing界面更新,可使用SwingWorker替代手动线程调度,更符合Swing线程模型规范。

内容的提问来源于stack exchange,提问作者Jessica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 12:05:19