java - страниц - убрать index php dle




Как дождаться завершения ряда потоков? (9)

Каков способ просто дождаться завершения всего процесса с резьбой? Например, допустим, у меня есть:

public class DoSomethingInAThread implements Runnable{

    public static void main(String[] args) {
        for (int n=0; n<1000; n++) {
            Thread t = new Thread(new DoSomethingInAThread());
            t.start();
        }
        // wait for all threads' run() methods to complete before continuing
    }

    public void run() {
        // do something here
    }


}

Как это изменить, поэтому метод main() останавливается в комментарии до тех пор, пока все методы run() потоков не выйдут? Благодаря!


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


В качестве альтернативы CountDownLatch вы также можете использовать CyclicBarrier, например

public class ThreadWaitEx {
    static CyclicBarrier barrier = new CyclicBarrier(100, new Runnable(){
        public void run(){
            System.out.println("clean up job after all tasks are done.");
        }
    });
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            Thread t = new Thread(new MyCallable(barrier));
            t.start();
        }       
    }

}    

class MyCallable implements Runnable{
    private CyclicBarrier b = null;
    public MyCallable(CyclicBarrier b){
        this.b = b;
    }
    @Override
    public void run(){
        try {
            //do something
            System.out.println(Thread.currentThread().getName()+" is waiting for barrier after completing his job.");
            b.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }       
}

Чтобы использовать CyclicBarrier в этом случае, bar.await () должен быть последним утверждением, т. Е. Когда ваш поток выполняется с его работой. CyclicBarrier можно использовать снова с помощью метода reset (). Чтобы процитировать javadocs:

CyclicBarrier поддерживает необязательную команду Runnable, которая запускается один раз на каждую барьерную точку после того, как последний поток в партии приходит, но до того, как будут выпущены какие-либо потоки. Это действие барьера полезно для обновления состояния shared-state до того, как какая-либо из сторон продолжит работу.


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

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

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


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

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


Один из способов - создать List Thread , создать и запустить каждый поток, добавив его в список. Как только все будет запущено, пройдите по списку и вызовите 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) невероятно гибко, и приведенный выше пример едва даже царапает поверхность.


Поскольку Martin K предложил java.util.concurrent.CountDownLatch похоже, является лучшим решением для этого. Просто добавив пример для того же

     public class CountDownLatchDemo
{

    public static void main (String[] args)
    {
        int noOfThreads = 5;
        // Declare the count down latch based on the number of threads you need
        // to wait on
        final CountDownLatch executionCompleted = new CountDownLatch(noOfThreads);
        for (int i = 0; i < noOfThreads; i++)
        {
            new Thread()
            {

                @Override
                public void run ()
                {

                    System.out.println("I am executed by :" + Thread.currentThread().getName());
                    try
                    {
                        // Dummy sleep
                        Thread.sleep(3000);
                        // One thread has completed its job
                        executionCompleted.countDown();
                    }
                    catch (InterruptedException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

            }.start();
        }

        try
        {
            // Wait till the count down latch opens.In the given case till five
            // times countDown method is invoked
            executionCompleted.await();
            System.out.println("All over");
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }

}

Создайте объект потока внутри первого цикла for.

for (int i = 0; i < threads.length; i++) {
     threads[i] = new Thread(new Runnable() {
         public void run() {
             // some code to run in parallel
         }
     });
     threads[i].start();
 }

И тогда так все говорят здесь.

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

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

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

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

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

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


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
   }
}






wait