Combining two Runnable objects

◇◆丶佛笑我妖孽 提交于 2019-12-06 10:43:49

Well you can certainly create a Runnable which just runs one runnable then the other:

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

More generally, you could make it take an Iterable<Runnable>, copy all the Runnable references, and then run them in order. For example:

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

Sure. Just create another runnable that calls the run methods of your two existing Runnable's as part of its implementation. You can make the wrapping Runnable purpose-built or generic with a list of Runnables, etc.

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

   return retVal;
}

Perhaps what's confusing you is association of Runnable with threads. The Runnable interface isn't tied to threads and doesn't by itself have any threading semantics, so you can easily combine it like above without somehow getting into trouble with thread states.

Yes you can of course combine them. In general though, there shouldn't be much inside a runnable except a call to some other object, to actually get the work done. Can you not just take the "insides" of the runnables you need and execute them in the context you want.

If you want to make sure things are simply executed one after the other, rather than at the same time you can use a SingleThreadExecutorService and give them the Runnables. It will execute one at a time.

If you really want to run multiple runnables then you can do it like this (the first RuntimeException will exit).

Note the static convenience method so you can say "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);
    }
}

Another variation.

public static Runnable combineRunnables(final Runnable... runnables) {
   return new Runnable() {
        public void run() {
            for(Runnable r: runnables) r.run();
        } 
   };
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!