从后台线程调用主线程上的函数

Ian*_*hop 4 java concurrency swing swingworker runnable

更新

我已经更新了这个问题,使用建议的SwingWorker类包含Java实现的源代码,以实现与Objective-C示例相同的结果.希望这将有助于未来的冒险家.

Document myDoc = ...;
Model myModel = ...;

SwingWorker analyzeDocument = new SwingWorker<Dictionary, Void>() {
    @Override
    public Dictionary doInBackground() {
        return myDoc.analyze();
    }

    @Override
    public void done() {
        try {
            stats = get();
            myModel.setDict(stats);
            myModel.setNeedsDisplay(true);
        } catch(InterruptedException ex) {
            // log
        } catch(ExecutionException ex) {
            // log
        }
    }
};

analyzeDocument.execute();
Run Code Online (Sandbox Code Playgroud)

原帖

在并发编程方面,我缺乏经验,我希望有人能够向我解释如何实现这一目标.

在Objective-C(使用GCD)中,您可以执行以下操作:

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
     NSDictionary *stats = [myDoc analyze];
     dispatch_async(dispatch_get_main_queue(), ^{
       [myModel setDict:stats];
       [myStatsView setNeedsDisplay:YES];
       [stats release];
     });
 });
Run Code Online (Sandbox Code Playgroud)

此代码将[myDoc analyze]在后台线程中执行,在回调函数之后更新将在主线程中执行的UI .换句话说,后台线程向主线程发送一个中断,将匿名函数添加到要调用的主线程队列中.显然我不能在Java中使用匿名函数,但这不是重点.

我有兴趣在Java中做这件事.我有一个Runnable对象在文件系统中做了很多东西.完成后,我想相应地更新UI.

为了在执行此操作时不挂起主线程(即:)backgroundThread.join();,我设置了后台线程来执行回调函数来更新UI.但这不是一个好主意,我不希望非GUI线程更新GUI.

我想到的其他一些想法是投票,但这似乎就是抛出一些循环.根据同样的判断,使用期货似乎也不是答案.这一切似乎都打败了异步操作的目的.

我能想到的唯一另一件事是SwingUtilities.invokeLater从后台线程使用并使用它来更新GUI.但我很好奇这将执行哪个线程.

也许我的看法只是扭曲了,但这似乎是一个非常重要的部分.我只是想以错误的方式解决这个问题吗?

Hov*_*els 6

您是否考虑过创建和使用SwingWorker对象?这允许您轻松地在线程背景中运行代码到事件线程,并且实际上也是Future对象,因此它可以返回结果,并且您可以在其done()方法中使用此结果来更新事件线程上的GUI .您甚至可以通过publish/ processmethod对在运行过程中对Swing事件线程进行调用.

有关这方面的更多信息,请查看:Swing中的并发性

  • @IanBishop:不,谢谢!你的投票给了我1000分的Java,给了我一个Java金徽章!:) (2认同)