2

在我的 SWT Java 应用程序中,我经常希望从 Display.syncExec() 调用中返回信息。到目前为止,我发现的最佳方法是:

final ArrayList<Integer> result = new ArrayList<Integer>();
GUI.display().syncExec(new Runnable(){ public void run() {
   MessageBox mb = /* ... */;
    /* set up messagebox */
   result.add(mb.open());
}});
if (SWT.OK == result.get(0)) { /* ... */ }

我认为这是允许的,因为 ArrayList 是线程安全的,但是我应该使用更好的容器还是更简单的方法?

4

5 回答 5

5

ArrayList不是线程安全的。您可以List使用Collections.synchronizedList. AtomicInteger但是,在您的情况或AtomicReference更一般的情况下使用它要简单得多。

final AtomicInteger resultAtomicInteger = new AtomicInteger();
Display.getCurrent().syncExec(new Runnable() { 
    public void run() {
        MessageBox mb = /* ... */;
            /* set up messagebox */
        resultAtomicInteger.set(mb.open());
}});
if (SWT.OK == resultAtomicInteger.get()) { /* ... */ }
于 2008-09-16T20:13:55.767 回答
3

我刚刚解决了这个问题,我的第一次尝试是类似的 - 数组或所需类型项目的列表。但过了一会儿,我编造了这样的东西:

abstract class MyRunnable<T> implements Runnable{
    T result;
}
MyRunnable<Integer> runBlock = new MyRunnable<Integer>(){
   MessageBox mb = /* ... */;
    /* set up messagebox */
   result = mb.open();
}
GUI.display().syncExec(runBlock);
runBlock.result; //holds a result Integer

它更整洁并删除了冗余变量。

顺便提一句。我真正的第一次尝试是使用 UIThreadRunnable,但我不想依赖 SWTBot,所以我放弃了这个解决方案。在我发现自己的解决方案后,他们在那里使用了类似的工作。

于 2012-01-20T12:28:41.010 回答
1

ArrayList不是线程安全的。从相关的Javadoc

请注意,此实现不同步。如果多个线程同时访问一个 ArrayList 实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步。

如果您需要 List 的线程安全实现,JDK 中(至少)提供了两个:CopyOnWriteArrayList 和 Vector。

于 2008-09-16T20:09:47.897 回答
1

您可以使用 Integer[1] 数组使其更简洁,但我认为它不能直接从匿名内部类内部更新非最终变量。

final Integer[] result = new Integer[1];

我认为您必须将结果声明为最终结果(但该更改不会影响您的代码)。由于当前线程阻塞直到内部线程完成,我认为您不需要担心同步(但您可能需要使变量违反以便看到结果)。

于 2008-09-16T20:14:43.783 回答
1

如果这种情况经常发生,您最好在流程和视图之间使用订阅/通知模型。您的视图订阅了应该触发该消息框的事件,并在满足条件时收到通知。

于 2008-09-19T11:58:31.913 回答