Как ожидать многих потоков для завершения?

Используете ли Вы Тестирование системы Команды или NUnit, лучшая практика должна создать отдельную Библиотеку классов для Ваших тестов. Просто добавление App.config к Вашему Тестовому проекту будет автоматически скопировано в Вашу папку мусорного ведра, когда Вы скомпилируете .

, Если бы Ваш код уверен в определенных тестах конфигурации, самый первый тест, я записал бы, проверяет это, конфигурационный файл доступен ( так, чтобы я знал, что я весьма нормален ):

<configuration>
   <appSettings>
       <add key="TestValue" value="true" />
   </appSettings>
</configuration>

И тест:

[TestFixture]
public class GeneralFixture
{
     [Test]
     public void VerifyAppDomainHasConfigurationSettings()
     {
          string value = ConfigurationManager.AppSettings["TestValue"];
          Assert.IsFalse(String.IsNullOrEmpty(value), "No App.Config found.");
     }
}

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

public class MyObject
{
     public void Configure(MyConfigurationObject config)
     {
          _enabled = config.Enabled;
     }

     public string Foo()
     {
         if (_enabled)
         {
             return "foo!";
         }
         return String.Empty;
     }

     private bool _enabled;
}

[TestFixture]
public class MyObjectTestFixture
{
     [Test]
     public void CanInitializeWithProperConfig()
     {
         MyConfigurationObject config = new MyConfigurationObject();
         config.Enabled = true;

         MyObject myObj = new MyObject();
         myObj.Configure(config);

         Assert.AreEqual("foo!", myObj.Foo());
     }
}
103
задан Stephen C 1 April 2017 в 00:43
поделиться

8 ответов

Вы помещаете все потоки в массив, запускаете их все, а затем получаете цикл

for(i = 0; i < threads.length; i++)
  threads[i].join();

Каждое соединение будет блокироваться до тех пор, пока соответствующий поток не завершится. Потоки могут завершаться в другом порядке, чем вы присоединяетесь к ним, но это не проблема: когда цикл завершается, все потоки завершаются.

157
ответ дан 24 November 2019 в 04:16
поделиться

Это можно сделать с помощью объекта «ThreadGroup» и его параметра activeCount :

0
ответ дан 24 November 2019 в 04:16
поделиться

Это будет комментарий, но я пока не могу комментировать.

Мартин K , мне любопытно, как бы вы использовали ThreadGroup . Вы делали это раньше?

Я вижу, что выше вы предлагаете проверить activeCount - оставив в стороне озабоченность Мартина v Лёвиса по поводу опроса на данный момент, у меня есть еще одно беспокойство с activeCount .

Предостережение: я не пробовал использовать это, поэтому я не эксперт в этом вопросе, но, согласно javadocs , он возвращает ] оценка количества активных потоков.

Лично мне было бы неприятно пытаться построить систему на основе оценки. У вас есть еще одна мысль, как это сделать, или я неправильно читаю javadoc?

2
ответ дан 24 November 2019 в 04:16
поделиться

В зависимости от ваших потребностей вы можете также захотеть проверить классы CountDownLatch и CyclicBarrier в пакете java.util.concurrent. Они могут быть полезны, если вы хотите, чтобы ваши потоки ожидали друг друга, или если вы хотите более детальный контроль над тем, как ваши потоки выполняются (например, ожидая в своем внутреннем исполнении, чтобы другой поток установил какое-то состояние). Вы также можете использовать CountDownLatch, чтобы сигнализировать всем вашим потокам о запуске одновременно, вместо того, чтобы запускать их один за другим при повторении цикла. В стандартной документации API есть пример этого, а также использование другого CountDownLatch для ожидания завершения выполнения всеми потоками.

3
ответ дан 24 November 2019 в 04:16
поделиться

Если вы составите список потоков, вы можете перебрать их и выполнить .join () для каждого, и ваш цикл завершится, когда все потоки будут иметь. Но я не пробовал.

http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join ()

3
ответ дан 24 November 2019 в 04:16
поделиться

Один из способов - создать Список из Thread s, создать и запустить каждый поток, добавляя его в список. Как только все будет запущено, вернитесь к списку и вызовите join () для каждого из них. Неважно, в каком порядке завершаются выполнение потоков, все, что вам нужно знать, это то, что к тому времени, когда завершится выполнение второго цикла, все потоки будут завершены.

Лучше использовать ExecutorService и связанных с ним методов:

List<Callable> callables = ... // assemble list of Callables here
                               // Like Runnable but can return a value
ExecutorService execSvc = Executors.newCachedThreadPool();
List<Future<?>> results = execSvc.invokeAll(callables);
// Note: You may not care about the return values, in which case don't
//       bother saving them

Использование ExecutorService (и всех новых вещей из Java 5 утилит параллелизма ) невероятно гибко, и приведенный выше пример едва ли касается поверхности.

37
ответ дан 24 November 2019 в 04:16
поделиться
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class DoSomethingInAThread implements Runnable
{
   public static void main(String[] args) throws ExecutionException, InterruptedException
   {
      //limit the number of actual threads
      int poolSize = 10;
      ExecutorService service = Executors.newFixedThreadPool(poolSize);
      List<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();

      for (int n = 0; n < 1000; n++)
      {
         Future f = service.submit(new DoSomethingInAThread());
         futures.add(f);
      }

      // wait for all tasks to complete before continuing
      for (Future<Runnable> f : futures)
      {
         f.get();
      }

      //shut down the executor service so that this thread can exit
      service.shutdownNow();
   }

   public void run()
   {
      // do something here
   }
}
24
ответ дан 24 November 2019 в 04:16
поделиться

Полностью избегайте класса Thread и вместо этого используйте более высокие абстракции, представленные в java.util.concurrent

Класс ExecutorService предоставляет метод invokeAll , который, кажется, делает именно то, что вы хотите.

8
ответ дан 24 November 2019 в 04:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: