Domanda

Dire per esempio che ho una chiamata RunnableA Runnable che fa qualcosa. Ho anche un Runnable chiamato RunnableB che fa qualcos'altro. C'è un modo che io possa combinare questi due Runnables qualche modo in modo che possano funzionare nello stesso thread?

La seconda parte della domanda è se questo è possibile, posso poi specificare l'ordine che verrà eseguito in?

EDIT !: Il motivo per cui ho voluto fare questo è stato perché ho bisogno di eseguire codice sul EDT ma alcune delle altre necessità di codice da eseguire su un altro thread. Si prega di dare un'occhiata al codice qui sotto.

Qualcosa di simile a questo


public final class CompoundRunnable implements Runnable
{
    private final Iterable runnables;

    public CompoundRunnable(Iterable runnables)
    {
        // From Guava. Easy enough to do by hand if necessary
        this.runnables = Lists.newArrayList(runnables);

    }

    public CompoundRunnable(Runnable... runnables)
    {
        this(Arrays.asList(runnables));
    }

    @Override
    public void run()
    {
        for (Runnable runnable : runnables)
        {
             runnable.run();
        }
    }
}


public void setStatusAndProgress(final String status,Runnable runnable)
    {
        Runnable startUpRunner = new Runnable()
        {
            public void run()
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        setStatus(status);
                        selfReference.getProgressBar().setIndeterminate(true);
                    }

                });
            }
        };
        Runnable cleanUpRunner = new Runnable()
        {
            public void run()
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        setStatus("");
                        getProgressBar().setIndeterminate(false);
                    }
                });
            }
        };

        Runnable theRunner = new CompoundRunnable(startUpRunner,runnable,cleanUpRunner);
        new Thread(theRunner).start();
    }

Scusate se questo non è spiegato bene, inviare commenti se avete bisogno di chiarimenti.

Grazie!

È stato utile?

Soluzione

Ebbene si può certamente creare un Runnable che ha appena eseguito un eseguibile poi l'altro:

public final class CompoundRunnable implements Runnable
{
    private final Runnable first;
    private final Runnable second;

    public CompoundRunnable(Runnable first, Runnable second)
    {
        this.first = first;
        this.second = second;
    }

    @Override
    public void run()
    {
        first.run();
        second.run();
    }
}

Più in generale, si potrebbe fare ci vuole un Iterable<Runnable>, copiare tutti i riferimenti Runnable, e poi eseguirli in ordine. Ad esempio:

public final class CompoundRunnable implements Runnable
{
    private final Iterable<Runnable> runnables;

    public CompoundRunnable(Iterable<Runnable> runnables)
    {
        // From Guava. Easy enough to do by hand if necessary
        this.runnables = Lists.newArrayList(runnables);
    }

    public CompoundRunnable(Runnable... runnables)
    {
        this(Arrays.asList(runnables));
    }

    @Override
    public void run()
    {
        for (Runnable runnable : runnables)
        {
             runnable.run();
        }
    }
}

Altri suggerimenti

Certo. Basta creare un eseguibile che chiama i metodi di esecuzione dei vostri due esistenti Runnable come parte della sua attuazione. È possibile effettuare l'involucro Runnable appositamente costruito o generico con un elenco di Runnables, ecc.

public Runnable combineRunnables(Runnable a, Runnable b)
{
   Runnable retVal = new Runnable()
   {
        public void run()
        {
            a.run();
            b.run();
        } 
   };

   return retVal;
}

Forse quello che sta confondendo voi è un'associazione di Runnable con fili. L'interfaccia Runnable non è legato a discussioni e non ha di per sé avere la semantica di threading, in modo da poter facilmente combinare come sopra senza entrare in qualche modo nei guai con gli stati di thread.

Sì, è possibile, naturalmente combinarli. In se generale, non ci dovrebbe essere molto più all'interno di un eseguibile, tranne una chiamata a un altro oggetto, per ottenere effettivamente il lavoro svolto. Si può non solo prendere le "viscere" delle runnables è necessario ed eseguirli nel contesto che si desidera.

Se si desidera assicurarsi che le cose sono semplicemente eseguiti uno dopo l'altro, piuttosto che allo stesso tempo è possibile utilizzare un SingleThreadExecutorService e dare loro le Runnables. Si eseguirà una alla volta.

Se si vuole veramente per eseguire più runnables allora si può fare in questo modo (il primo RuntimeException uscirà).

Si noti il ??metodo comodo statica in modo da poter dire "new Thread (CompositeRunnable.combine (a, b, c, d ....))"

public class CompositeRunnable implements Runnable {

    private final Runnable[] runnables;

    public CompositeRunnable(Runnable... runnables) {
        this.runnables = runnables;
    }

    public void run() {
        for (Runnable runnable : runnables) {
            runnable.run();
        }
    }

    public static Runnable combine(Runnable... runnables) {
        return new CompositeRunnable(runnables);
    }
}

Un'altra variante.

public static Runnable combineRunnables(final Runnable... runnables) {
   return new Runnable() {
        public void run() {
            for(Runnable r: runnables) r.run();
        } 
   };
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top