【问题标题】:Concurrency conflict trying to use BufferedWriter in JTextArea尝试在 JTextArea 中使用 BufferedWriter 的并发冲突
【发布时间】:2014-10-22 23:08:26
【问题描述】:

我遇到了某种输出到 JTextArea 的线程问题。我设置了一个 BufferedWriter 来写入这个文本区域,但由于某种原因,在当前函数完成之前它不会写入这个区域。例如,我有这段代码可以检查 URL 列表以查看它们是好是坏:

for( final String s : urls ){
    String sContent = IO.getURLContent( s );
    if( sContent == null ){
        writeLine( "Error " + s );
    } else {
        writeLine( "Worked " + s );
    }
}

void writeLine( String sLineText ) throws java.io.IOException {
    mbwriter.write(sLineText);
    mbwriter.newLine();
    mbwriter.flush();
}

输出仅在循环完成后发生,即使在检查每个 URL 后正在刷新写入器。我尝试将 IO 操作放在一个单独的线程中,如下所示:

for( final String s : urls ){
SwingUtilities.invokeLater( new Runnable() {
    public void run(){
        String sContent = IO.getURLContent( s );
            if( sContent == null ){
                writeLine( "Error " + s );
            } else {
                writeLine( "Worked " + s );
            }
        }
    }
} );
}

不过没关系,输出依然是阻塞的,直到整个循环完成。

请注意,整个 Swing 界面在此操作期间挂起。你不能点击任何东西,即使是靠近窗户的地方。界面完全冻结。

【问题讨论】:

  • 为了尽快获得更好的帮助,请发布MCVE(最小完整可验证示例)。
  • 鉴于没有'?'用这些话 - 你的问题是什么?

标签: java swing concurrency


【解决方案1】:

这是意料之中的。

Swing 是单线程环境,也就是说,如果你阻塞了运行时间长的 Event Dispatching Thread 或者阻塞了方法调用,它将无法处理发布到 Event Queue 的新事件,从而有效地使你的 UI “挂起”

听起来您的第一个示例在 EDT 的上下文中运行,而您的第二个示例仍在 EDT 的上下文中运行,但是在 EDT 能够之后的某个时间安排更新,再次处理事件队列...

invokeLater 正在事件队列中放置一个事件,以便 EDT “稍后”处理

考虑改用 SwingWorker,它提供了在后台运行代码的能力,但提供了允许您通过 publishprocess 方法将更新同步到 EDT 的方法

Concurrency in SwingWorker Threads and SwingWorker了解更多详情

举个例子……

public class URLWorker extends SwingWorker<List<String>, String> {

    private List<String> urls;
    private BufferedWriter bw;

    public URLWorker(List<String> urls, BufferedWriter bw) {
        this.urls = urls;
        this.bw = bw;
    }

    @Override
    protected void process(List<String> chunks) {
        for (String result : chunks) {

            try {
                bw.write(result);
                bw.newLine();
            } catch (IOException exp) {
                firePropertyChange("error", null, ex);
            }

        }
        try {
            bw.flush();
        } catch (IOException ex) {
            firePropertyChange("error", null, ex);
        }
    }

    @Override
    protected List<String> doInBackground() throws Exception {
        List<String> results = new ArrayList<String>(urls.size());
        for (final String s : urls) {
            String sContent = IO.getURLContent(s);
            StringBuilder result = new StringBuilder(s);
            if (sContent == null) {
                result.insert(0, "Error ");
            } else {
                result.insert(0, "Worked ");
            }
            publish(result.toString());
            results.add(result.toString());
        }
        return results;
    }
}

【讨论】:

    猜你喜欢
    • 2013-12-21
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 2018-01-21
    • 2016-09-24
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    相关资源
    最近更新 更多