3

たとえば、何かを実行する RunnableA という Runnable があるとします。また、別のことを行う RunnableB という Runnable もあります。これら 2 つの Runnables を何らかの方法で組み合わせて、同じスレッドで実行する方法はありますか?

質問の 2 番目の部分は、これが可能である場合、それらが実行される順序を指定できますか?

EDIT!: 私がこれをやりたかった理由は、EDT でコードを実行する必要があるが、他のコードの一部は別のスレッドで実行する必要があるためです。以下のコードを見てください。

このようなもの


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();
    }

これがうまく説明されていない場合は申し訳ありませんが、明確化が必要な場合はコメントを投稿してください。

ありがとう!

4

5 に答える 5

8

確かに、 Runnable1 つのランナブルを実行してからもう 1 つのランナブルを実行する を作成できます。

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();
    }
}

より一般的には、 を取得しIterable<Runnable>、すべての参照をコピーしてから、Runnableそれらを順番に実行できます。例えば:

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();
        }
    }
}
于 2011-01-11T20:01:58.777 に答える
3

もちろん。実装の一部として、2 つの既存の Runnable の run メソッドを呼び出す別の runnable を作成するだけです。Runnable のリストなどを使用して、Runnable 専用または汎用のラッピングを作成できます。

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

   return retVal;
}

おそらく、あなたを混乱させているのは、 Runnable とスレッドの関連付けです。Runnable インターフェースはスレッドに関連付けられておらず、それ自体にはスレッドのセマンティクスがないため、上記のように簡単に組み合わせることができ、スレッドの状態で何らかの問題が発生することはありません。

于 2011-01-11T20:01:39.077 に答える
2

はい、もちろん組み合わせることができます。ただし、一般的には、実際に作業を完了するために、他のオブジェクトへの呼び出しを除いて、ランナブル内に多くのものを含めるべきではありません。必要なランナブルの「内部」を取得して、必要なコンテキストで実行することはできません。

物事が同時に実行されるのではなく、単純に次々に実行されることを確認したい場合は、SingleThreadExecutorService を使用してそれらに Runnables を与えることができます。一度に 1 つずつ実行されます。

本当に複数のランナブルを実行したい場合は、次のように実行できます (最初の RuntimeException が終了します)。

「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);
    }
}
于 2011-01-11T20:12:31.767 に答える
2

別のバリエーション。

public static Runnable combineRunnables(final Runnable... runnables) {
   return new Runnable() {
        public void run() {
            for(Runnable r: runnables) r.run();
        } 
   };
}
于 2011-01-11T21:51:45.977 に答える