Объединение двух управляемых объектов


Скажем, например, что у меня есть Runnable под названием RunnableA, который что-то делает. У меня также есть Runnable под названием RunnableB, который делает что-то еще. Есть ли способ, которым я могу объединить эти два Runnables так, чтобы они работали в одном потоке?

Вторая часть вопроса заключается в том, если это возможно, могу ли я тогда указать порядок, в котором они будут выполняться?

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

4 ответа:

Ну, вы, конечно, можете создать Runnable, который просто запускает один runnable, а затем другой:

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

Конечно. Просто создайте еще один 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 не должно быть ничего, кроме вызова какого-то другого объекта, чтобы фактически выполнить работу. Вы не можете просто взять "внутренности" нужных вам runnables и выполнить их в нужном вам контексте.

Если вы хотите убедиться, что вещи просто выполняются один за другим, а не в то же время вы можете использовать SingleThreadExecutorService и дать им Runnables. Он будет выполнять один за другим. время.

Если вы действительно хотите запустить несколько runnables, то вы можете сделать это так (первое RuntimeException завершится).

Обратите внимание на статический метод удобства, чтобы вы могли сказать " new Thread (CompositeRunnable.комбинируйте(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);
    }
}

Еще одна вариация.

public static Runnable combineRunnables(final Runnable... runnables) {
   return new Runnable() {
        public void run() {
            for(Runnable r: runnables) r.run();
        } 
   };
}