Domanda

Nella mia app Java SWT desidero spesso restituire informazioni dall'interno di una chiamata Display.syncExec().Il modo migliore che ho trovato finora per farlo è:

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)) { /* ... */ }

Penso che ciò sia consentito perché ArrayList è thread-safe, ma esiste un contenitore migliore che dovrei utilizzare o un modo del tutto più semplice?

È stato utile?

Soluzione

ArrayList non è thread-safe.È possibile ottenere un file thread-safe List con Collections.synchronizedList.Tuttavia, è molto più semplice utilizzare un file AtomicInteger nel tuo caso o AtomicReference in un caso più generale.

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()) { /* ... */ }

Altri suggerimenti

Ho appena affrontato questo problema e il mio primo tentativo è stato simile: array o elenco di elementi del tipo desiderato.Ma dopo un po' ho inventato qualcosa del genere:

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

È molto più ordinato e rimuove le variabili ridondanti.

A proposito.Il mio primo vero tentativo è stato utilizzare UIThreadRunnable, ma non volevo la dipendenza SWTBot, quindi ho abbandonato questa soluzione.Dopo aver creato la mia soluzione, ho scoperto che usano un lavoro simile lì dentro.

ArrayList è non thread-safe.Dal pertinente Javadoc:

Si noti che questa implementazione non è sincronizzata.Se più thread accedono a un'istanza di ArrayList contemporaneamente e almeno uno dei thread modifica strutturalmente l'elenco, deve essere sincronizzato esternamente.

Se hai bisogno di un'implementazione thread-safe di List, ce ne sono (almeno) due fornite nel JDK:CopyOnWriteArrayList e Vector.

Potresti usare un array Integer[1] per renderlo più conciso ma non penso che possa aggiornare direttamente una variabile non finale dall'interno di una classe interna anonima.

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

Pensavo che dovessi dichiarare i risultati come finali (ma quella modifica non avrebbe influenzato il tuo codice).Poiché il thread corrente si blocca fino al completamento del thread interno, non penso che tu debba preoccuparti della sincronizzazione (ma potresti dover violare la variabile in modo da vedere il risultato).

Se ciò accade spesso, è meglio utilizzare il modello di iscrizione/notifica tra il processo e la visualizzazione.La tua vista si iscrive all'evento che dovrebbe attivare quella finestra di messaggio e ricevere una notifica quando le condizioni sono soddisfatte.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top