2009-10-23 2 views
3

У меня есть один основной поток, который запускает еще 10 других потоков. Я хочу, чтобы основной поток был закончен только после прекращения всех остальных потоков. Поэтому я должен вызвать join() для других 10 потоков перед запуском или после их запуска. Например:Как присоединиться к одному потоку с другим в java?

// in the main() method of Main thread 
Thread [] threads = new Thread[10]; 
for(int i = 0; i < 10; i++) { 
    // ParserThread() is a runnable thread 
    threads[i] = new Thread(new ParserThread()); 
    threads[i].join(); 
    threads[i].start(); 
} 
System.out.println("All threads have been finished"); // line no. 9 
  1. Так как в приведенном выше примере, я должен позвонить присоединиться() перед запуском() или после запуска().
  2. Будет ли управление возвращаться к строке №. 9 только после завершения всех потоков.
  3. Когда был запущен метод запуска любой нити, тогда эта нить погибнет или останется в живых. Если это произойдет, то, как закончить все потоки, когда закончен их метод запуска, означает, что элемент управления возвращается к строке no. 9

ответ

7

Вызов join() на потоке имеет смысл после запускается поток только. Вызывающий абонент join() остановится и ждет, пока другой поток не закончит то, что он делает. Таким образом, вы можете это сделать:

// in the main() method of Main thread 
Thread [] threads = new Thread[10]; 
for(int i = 0; i < 10; i++) { 
    // ParserThread() is a runnable thread 
    threads[i] = new Thread(new ParserThread()); 
    threads[i].start(); 
} 
System.out.println("All threads have been started"); 
for(int i = 0; i < 10; i++) { 
    threads[i].join(); 
} 
System.out.println("All threads have been finished"); 
+0

Могу ли я вставить инструкцию «threads [i] .join()» в первый цикл цикла после инструкции «threads.start()». –

+2

Вы можете, но тогда ваша вторая нить не начнется, пока не закончится первый. С моим выше кодом все 10 потоков будут работать параллельно, пока они не остановятся. –

1

Вы должны сначала начать весь поток, а затем начать их соединение. Join будет возвращать direct, если вызывается до начала потока.

6

Я рекомендую использовать низкоуровневые конструкции темы хотели присоединиться(), и вместо того, чтобы, используя материал более высокого уровня в java.util.concurrent, как CyclicBarrier:

Слуховой синхронизации, которая позволяет набора нитей все ждут для каждого других, чтобы достичь общей точки барьера. CyclicBarriers полезны в программах с участием фиксированного размера потоков, которые должны время от времени ждать друг для друга. Барьер называется циклическим, потому что он может быть повторно использован после ожидающих потоков.

Использование гораздо более очевидным, что Thread.join() и гораздо менее склонны к странным ошибкам.

5

Вместо того чтобы писать свой собственный код, код использовать ThreadPoolExecutor делать то, что вам нужно:

ThreadPoolExecutor executor = new ThreadPoolExecutor(0, 10, 2, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); 

for (int i = 0; i < 10; i++) 
    executor.execute(new ParserThread()); 

try { 
    executor.shutdown(); 
    executor.awaitTermination(10, TimeUnit.MINUTES); 
} catch (final InterruptedException e) { 
    // handle 
} 

Таким образом, вы можете легко использовать меньше темы, чтобы сделать больше задач, если вы хотите - без изменения кода ,

+0

вы можете ответить на мой другой вопрос по адресу http://stackoverflow.com/questions/1611862/how-to-stop-threads-in-java –

+0

Вы захотите поместить этот оператор создания ThreadPoolExecutor внутри блока try, хотя – skaffman

+0

По какой причине вы поместили бы его в блок try? – sfussenegger

0

Дело может быть в том, что вы хотите присоединиться к группе потоков. См Javadoc для

http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html

void solve(Executor e, 
       Collection<Callable<Result>> solvers) 
    throws InterruptedException, ExecutionException { 
     CompletionService<Result> ecs 
      = new ExecutorCompletionService<Result>(e); 
     for (Callable<Result> s : solvers) 
      ecs.submit(s); 
     int n = solvers.size(); 
     for (int i = 0; i < n; ++i) { 
      Result r = ecs.take().get(); 
      if (r != null) 
       use(r); 
     } 
    } 

Для тривиальных сценариев (одна нить), Thread.join() достаточно.

Смежные вопросы