모든 스레드 프로세스가 완료 될 때까지 기다리는 방법은 무엇입니까? 예를 들어 다음과 같이 가정 해 보겠습니다.
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()
메서드가 종료 될 때까지 메서드가 주석에서 일시 중지 되도록 어떻게 변경 합니까? 감사!
답변
모든 스레드를 배열에 넣고 모두 시작한 다음 루프가 있습니다.
for(i = 0; i < threads.length; i++)
threads[i].join();
각 조인은 해당 스레드가 완료 될 때까지 차단됩니다. 스레드는 결합하는 순서와 다른 순서로 완료 될 수 있지만 문제는 아닙니다. 루프가 종료되면 모든 스레드가 완료됩니다.
답변
한 가지 방법은 수 있도록하는 것입니다 List
의 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 동시성 유틸리티 의 모든 새로운 기능 )를 사용하는 것은 매우 유연하며 위의 예는 표면을 거의 긁지 않습니다.
답변
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
}
}
답변
join()
이전 API 인 대신 사용할 수 있습니다. CountDownLatch . 귀하의 요구 사항을 충족시키기 위해 귀하의 코드를 아래와 같이 수정했습니다.
import java.util.concurrent.*;
class DoSomethingInAThread implements Runnable{
CountDownLatch latch;
public DoSomethingInAThread(CountDownLatch latch){
this.latch = latch;
}
public void run() {
try{
System.out.println("Do some thing");
latch.countDown();
}catch(Exception err){
err.printStackTrace();
}
}
}
public class CountDownLatchDemo {
public static void main(String[] args) {
try{
CountDownLatch latch = new CountDownLatch(1000);
for (int n=0; n<1000; n++) {
Thread t = new Thread(new DoSomethingInAThread(latch));
t.start();
}
latch.await();
System.out.println("In Main thread after completion of 1000 threads");
}catch(Exception err){
err.printStackTrace();
}
}
}
설명 :
-
CountDownLatch
귀하의 요구 사항에 따라 주어진 카운트 1000으로 초기화되었습니다. -
각 작업자 스레드
DoSomethingInAThread
는CountDownLatch
생성자에 전달 된를 감소시킵니다 . -
CountDownLatchDemo
await()
카운트가 0이 될 때까지 메인 스레드 . 카운트가 0이되면 출력에서 줄 아래에있게됩니다.In Main thread after completion of 1000 threads
오라클 문서 페이지에서 더 많은 정보
public void await()
throws InterruptedException
스레드가 인터럽트되지 않는 한 현재 스레드가 래치가 0이 될 때까지 대기하도록합니다.
다른 옵션은 관련 SE 질문을 참조하십시오.
모든 스레드가 Java에서 작업을 마칠 때까지 기다립니다.
답변
Thread 클래스를 아예 피하고 대신 java.util.concurrent에서 제공하는 더 높은 추상화를 사용하십시오.
ExecutorService 클래스는 원하는 작업을 수행하는 것 같은 invokeAll 메소드를 제공합니다 .
답변
사용하는 것이 좋습니다 java.util.concurrent.CountDownLatch
. javadocs의 예
답변
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();
}
}
}