Какой лучший способ вернуть переменные из syncExec? - PullRequest
2 голосов
/ 17 сентября 2008

В моем приложении 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 является потокобезопасным, но есть ли лучший контейнер, который я должен использовать, или более простой способ?

Ответы [ 5 ]

5 голосов
/ 17 сентября 2008

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()) { /* ... */ }
3 голосов
/ 20 января 2012

Я только что решил эту проблему, и моя первая попытка была похожей - массив или список элементов нужного типа. Но через некоторое время я придумал что-то вроде этого:

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, поэтому я отбросил это решение. После того, как я сделал свое собственное решение, я обнаружил, что они используют похожую работу там.

1 голос
/ 19 сентября 2008

Если это происходит часто, вам лучше использовать модель подписки / уведомления между вашим процессом и представлением. Ваше представление подписывается на событие, которое должно вызвать это окно сообщения, и получает уведомление при выполнении условий.

1 голос
/ 17 сентября 2008

Вы можете использовать массив Integer [1], чтобы сделать его более лаконичным, но я не думаю, что он может напрямую обновлять нефинальную переменную внутри анонимного внутреннего класса.

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

Я думал, что вам нужно объявить результаты как окончательные (но это изменение не повлияет на ваш код). Поскольку текущий поток блокируется до завершения внутреннего потока, я не думаю, что вам нужно беспокоиться о синхронизации (но вам, возможно, придется заставить переменную нарушать ее, чтобы увидеть результат).

1 голос
/ 17 сентября 2008

ArrayList не потокобезопасен. От соответствующего Javadoc :

Обратите внимание, что эта реализация не синхронизированы. Если несколько потоков получить доступ к экземпляру ArrayList одновременно, и по крайней мере один из темы изменяет список структурно он должен быть синхронизирован внешне.

Если вам нужна поточно-ориентированная реализация List, в JDK есть (как минимум) два: CopyOnWriteArrayList и Vector.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...