2011-01-11 3 views
2

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

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

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

Извините, если это разве хорошо объяснил, комментировать, если вам нужно уточнение.

Спасибо!

+0

Если вам нужно, чтобы они выполнялись в одном потоке в заданном порядке, это не совсем многопоточная проблема. Вы можете извлечь свой код из runnables? – Juliet

ответ

8

Ну вы конечно можете создать 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(); 
     } 
    } 
} 
+0

Большое спасибо. Я немного изменил ваш код и использовал его в приведенном выше примере. Можете ли вы сообщить мне, что вы думаете? – user489041

+0

@ user489041: Ну, вы удалили дженерики, чтобы начать с ... почему? –

+0

@Jon Skeet Я не мог использовать функцию List.newArrayList (runnables). Является ли эта часть com.google.common.collect.Lists? – user489041

3

Несомненно. Просто создайте еще один runnable, который вызывает методы запуска ваших двух существующих Runnable как часть его реализации. Вы можете сделать обертывание Runnable специально сконструированным или родовой со списком Runnables и т.д.

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

    return retVal; 
} 

Возможно, что смущает вас есть ассоциация Runnable с потоками. Интерфейс Runnable не привязан к потокам и сам по себе не имеет семантики потоков, поэтому вы можете легко объединить его, как описано выше, без каких-либо проблем с состояниями потоков.

+0

Да, я думаю, именно поэтому я запутался. Я думаю, что я об этом думаю.Я искал общий способ, который я мог бы запустить, и выключить код на EDT, а затем запустить некоторый рабочий код в своем потоке. Вот почему я задавался вопросом, могу ли я объединить их таким образом. Моя попытка, основанная на ответах, была опубликована выше. – user489041

+0

Вероятно, следует перехватывать исключения из первого и передавать его обработчику неперехваченных исключений. К сожалению, «Runnable» дается так мало смысла. –

2

Да, конечно, вы можете комбинировать их. В общем случае, не должно быть много внутри runnable, кроме вызова какого-либо другого объекта, чтобы фактически выполнить работу. Можете ли вы не просто взять «внутренности» используемых вами стопок и выполнить их в нужном вам контексте.

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

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

Примечания статического метода удобства, так что вы можете сказать: "Новая тема (CompositeRunnable.combine (а, б, в, г ....))"

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

Другим вариантом.

public static Runnable combineRunnables(final Runnable... runnables) { 
    return new Runnable() { 
     public void run() { 
      for(Runnable r: runnables) r.run(); 
     } 
    }; 
} 
Смежные вопросы