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

无法通过Jsch的SftpProgressMonitor更新Java Swing UI的原因排查

问题解析:SFTP进度更新为何要等操作完成才显示

核心原因

你误以为SftpProgressMonitor的回调是在EDT(事件调度线程)中执行,但实际上JSch的SFTP传输操作(比如ChannelSftp.put/get)是阻塞式同步调用,且init()、count()这些回调方法会在SFTP操作的工作线程里触发,而非EDT。

Swing的UI组件和数据模型(比如DefaultTableModel)必须在EDT中更新,非EDT线程直接操作会导致:

  • 线程安全问题(Swing不是线程安全的)
  • UI更新事件无法被EDT及时处理,所有更新会积压到SFTP线程结束后才一次性渲染,所以你只能看到最终的100%状态。

哪怕你调用repaint()/revalidate(),因为这些调用是在非EDT线程发起的,Swing依然无法及时处理刷新请求。

修复方案

把所有涉及UI/TableModel更新的代码,通过SwingUtilities.invokeLater()包装,强制放到EDT中执行:

public class MySftpProgressMonitor implements SftpProgressMonitor {

    JTable table = getTableReference();
    DefaultTableModel tableModel = getTableModelReference();
    private long totalBytes; // 保存总字节数,用于计算百分比

    @Override
    public boolean count(long bytes) {
        int percentage = computePercentage(bytes);
        // 把UI更新放到EDT执行
        SwingUtilities.invokeLater(() -> {
            table.setValueAt(percentage, 0, 1);
        });
        return true;
    }

    @Override
    public void end() {
        // 操作结束后的UI更新也放到EDT
        SwingUtilities.invokeLater(() -> {
            table.setValueAt(100, 0, 1);
        });
    }

    @Override
    public void init(int op, String src, String dest, long maxBytes) {
        this.totalBytes = maxBytes; // 保存总字节数
        Object[] rowData = {src, 0};
        // 添加行的操作放到EDT
        SwingUtilities.invokeLater(() -> {
            tableModel.addRow(rowData);
        });
    }

    private int computePercentage(long transferredBytes) {
        if (totalBytes == 0) return 0;
        return (int) ((transferredBytes * 100) / totalBytes);
    }
}

额外说明

  1. 你提到的“使用Worker线程避免阻塞UI”是正确的最佳实践——即使修复了回调的EDT问题,如果SFTP操作是在EDT中发起的,整个UI依然会被卡住,直到传输完成。正确流程应该是:
    • 在SwingWorker的doInBackground()中执行SFTP传输逻辑
    • 通过SwingWorker的publish()/process()方法更新进度,或者用上面的invokeLater()方式
  2. 确保getTableReference()和getTableModelReference()返回的是UI线程创建的组件实例,避免线程引用问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:42:31