source

다른 스레드가 완료되었는지 확인하는 방법

itover 2023. 2. 4. 08:23
반응형

다른 스레드가 완료되었는지 확인하는 방법

는 서드 named named named named named named named named named named named named named named named 라는 이름의 물건을 있다.StartDownload()3월 3일

각 스레드의 실행이 완료되면 알림을 받으려면 어떻게 해야 합니까?

스레드 중 하나(또는 모두)가 완료되었는지 아직 실행 중인지 알 수 있는 방법이 있습니까?

여기에는 여러 가지 방법이 있습니다.

  1. 메인 스레드에서 Thread.join()을 사용하여 각 스레드가 완료될 때까지 블로킹 방식으로 기다립니다.
  2. 각 스레드가 완료될 때까지 대기하려면 [Thread.isAlive()]를 폴링 방식으로 선택합니다(일반적으로 권장되지 않음).
  3. 문제의 각 스레드에 대해 비정통적인 경우 setUncaughtExceptionHandler를 호출하여 오브젝트 내의 메서드를 호출하고 완료 시 각 스레드가 수집되지 않은 예외를 발생시키도록 프로그래밍합니다.
  4. java.util.concurrent의 잠금, 동기화 또는 메커니즘을 사용합니다.
  5. 보다 정통적인 방법으로 기본 스레드에 수신인을 작성한 후 각 스레드가 수신인에게 완료되었음을 알리도록 프로그래밍합니다.

아이디어 #5의 구현 방법우선 인터페이스를 작성하는 방법이 있습니다.

public interface ThreadCompleteListener {
    void notifyOfThreadComplete(final Thread thread);
}

그런 다음 다음 클래스를 만듭니다.

public abstract class NotifyingThread extends Thread {
  private final Set<ThreadCompleteListener> listeners
                   = new CopyOnWriteArraySet<ThreadCompleteListener>();
  public final void addListener(final ThreadCompleteListener listener) {
    listeners.add(listener);
  }
  public final void removeListener(final ThreadCompleteListener listener) {
    listeners.remove(listener);
  }
  private final void notifyListeners() {
    for (ThreadCompleteListener listener : listeners) {
      listener.notifyOfThreadComplete(this);
    }
  }
  @Override
  public final void run() {
    try {
      doRun();
    } finally {
      notifyListeners();
    }
  }
  public abstract void doRun();
}

각각의 됩니다.NotifyingThread「」를 실장하는 에,run()doRun()따라서 작업이 완료되면 알림을 기다리는 모든 사용자에게 자동으로 알립니다.

적어도 알림을 를 에서 해당 를 "알림"으로 합니다.implement ThreadCompleteListener그리고 각 스레드를 작성한 직후 청취자 목록에 추가합니다.

NotifyingThread thread1 = new OneOfYourThreads();
thread1.addListener(this); // add ourselves as a listener
thread1.start();           // Start the Thread

각 종료되면, 「」는 「」를 참조해 .notifyOfThreadComplete메서드는 방금 완료(또는 크래시)한 스레드 인스턴스에서 호출됩니다.

해 주십시오.implements Runnableextends Thread★★★★★★에NotifyingThread스레드 확장은 보통 새 코드에서는 권장되지 않습니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 경우, 이 항목을 변경할 수 있습니다.NotifyingThread implement (실행 클래스)Runnable스레드를 관리하는 코드를 변경해야 합니다.이 작업은 매우 간단합니다.

CyclicBarrier를 사용한 솔루션

public class Downloader {
  private CyclicBarrier barrier;
  private final static int NUMBER_OF_DOWNLOADING_THREADS;

  private DownloadingThread extends Thread {
    private final String url;
    public DownloadingThread(String url) {
      super();
      this.url = url;
    }
    @Override
    public void run() {
      barrier.await(); // label1
      download(url);
      barrier.await(); // label2
    }
  }
  public void startDownload() {
    // plus one for the main thread of execution
    barrier = new CyclicBarrier(NUMBER_OF_DOWNLOADING_THREADS + 1); // label0
    for (int i = 0; i < NUMBER_OF_DOWNLOADING_THREADS; i++) {
      new DownloadingThread("http://www.flickr.com/someUser/pic" + i + ".jpg").start();
    }
    barrier.await(); // label3
    displayMessage("Please wait...");
    barrier.await(); // label4
    displayMessage("Finished");
  }
}

label0 - 실행 스레드 수와 같은 파티 수와 실행 메인 스레드용 1개를 더한 순회 장벽이 생성됩니다(startDownload()가 실행 중).

라벨 1 - n번째 다운로드쓰레드가 대기실로 들어갑니다.

라벨 3 - NUMBER_OF_DOWNLOADING_THREADS가 대기실에 들어왔습니다.실행의 메인 스레드는 다운로드 작업을 거의 동시에 시작하도록 해방합니다.

라벨 4 - 메인 실행 스레드가 대기실로 들어갑니다.이것은 코드에서 가장 이해하기 어려운 부분입니다.두 번째 대기실에 어떤 실이 들어가든 상관없습니다.마지막으로 룸에 들어온 스레드가 다른 모든 다운로드 스레드의 다운로드 작업이 완료되었는지 확인하는 것이 중요합니다.

라벨 2 - n번째 다운로드Thread는 다운로드 작업을 마치고 대기실로 들어갑니다.이 스레드가 마지막 스레드일 경우(NUMBER_OF_DOWNLOADING_THREADS가 이미 입력되어 있는 경우) 메인 스레드는 다른 모든 스레드의 다운로드가 완료된 경우에만 실행을 계속합니다.

이 솔루션을 사용하는 것이 좋습니다.java.util.concurrent조쉬 블로흐 브라이언 괴츠

「 」를하고 있지 않은 경우java.util.concurrent.*직접 을 책임지고 스레드를 사용하는 이 좋습니다.그러면 아마join()아, 네, 이겁니다.먼저 확장하다Runnable「 」 「 」 。

public interface CallbackRunnable extends Runnable {
    public void callback();
}

그런 다음 실행 파일을 실행하는 실행자를 만들고 실행이 완료되면 다시 전화하십시오.

public class CallbackExecutor implements Executor {

    @Override
    public void execute(final Runnable r) {
        final Thread runner = new Thread(r);
        runner.start();
        if ( r instanceof CallbackRunnable ) {
            // create a thread to perform the callback
            Thread callerbacker = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        // block until the running thread is done
                        runner.join();
                        ((CallbackRunnable)r).callback();
                    }
                    catch ( InterruptedException e ) {
                        // someone doesn't want us running. ok, maybe we give up.
                    }
                }
            });
            callerbacker.start();
        }
    }

}

은 른른른 your your your your your your the the the the에 대해서입니다.CallbackRunnable에 '를 수 .따서 、 를를 、public void uncaughtException(Throwable e);행 입력과 실행자에 스레드를 설치합니다.Unaughted Exception Handler 。

실제로 건java.util.concurrent.Callable 을 꼭 .java.util.concurrent신신면

끝날 때까지 기다릴까요?이 경우 Join 메서드를 사용합니다.

체크하고 싶은 경우 isAlive 속성도 있습니다.

스레드 인스턴스를 반환하는 getState()를 사용하여 스레드 인스턴스를 조회할 수 있습니다.다음 값 중 하나를 포함하는 상태 열거:

*  NEW
  A thread that has not yet started is in this state.
* RUNNABLE
  A thread executing in the Java virtual machine is in this state.
* BLOCKED
  A thread that is blocked waiting for a monitor lock is in this state.
* WAITING
  A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
* TIMED_WAITING
  A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
* TERMINATED
  A thread that has exited is in this state.

다만, 3명의 아이가 끝나기를 기다리는 마스터 스레드가 있는 것이 좋다고 생각합니다만, 나머지 3명이 끝나면 마스터는 실행을 계속합니다.

,도할 수 .Executors오브젝트를 지정하여 ExecutorService 스레드 풀을 만듭니다.그 후 를 사용합니다.invokeAll각 스레드를 실행하고 Futures를 검색하기 위한 메서드를 제공합니다.이치노은 풀을 한 다음, '하다'를 호출하는 입니다.awaitTermination이치노해 주세요.shutdown )을 클릭합니다. ( ) () () () () 。

지난 6년간 멀티 스레드 전선에서 많은 것이 바뀌었습니다.

「 」를 하는 대신에, 「 」를 사용합니다.join() A를 할 수 있습니다.PI 그 pi잠 pi pi

1. 이그제큐티브 서비스 invokeAll()

지정된 작업을 실행하여 모든 작업이 완료되면 상태 및 결과를 보유한 미래 목록을 반환합니다.

2. 카운트 다운 래치

다른 스레드에서 수행 중인 일련의 작업이 완료될 때까지 하나 이상의 스레드가 대기할 수 있는 동기화 보조 도구입니다.

A CountDownLatch는 지정된 카운트로 초기화됩니다.이 될 됩니다.되기 때문입니다.countDown()모든 대기 스레드가 해제되고 이후의 호출이 즉시 반환되는 메서드입니다.이것은 원샷 현상입니다.을 사용하다카운트를 리셋하는 버전이 필요한 경우는, CyclicBarrier 의 사용을 검토해 주세요.

3. Fork Join Pool 또는newWorkStealingPool()executors는 다른 방법입니다.

모두 한다.FutureExecutorService 콜을 합니다.get()Future 표시

관련 SE 질문을 살펴보십시오.

자신의 실이 만들어질 때까지 어떻게 기다리죠?

실행자:작업이 반복적으로 생성되는 경우 모든 작업이 완료될 때까지 동기적으로 대기하려면 어떻게 해야 합니까?

스레드 클래스용 javadoc을 보는 것이 좋습니다.

스레드 조작에는 여러 가지 메커니즘이 있습니다.

  • 에서는, 「」를 사용할 수 있습니다.join()3개의 스레드를 순차적으로 실행한 후 3개가 모두 완료될 때까지 진행되지 않습니다.

  • 생성된 스레드의 스레드 상태를 정기적으로 폴링합니다.

  • 된 모든 .ThreadGroupactiveCount() ThreadGroup0이 될 .

  • 스레드간 통신용으로 커스텀콜백 또는 리스너 타입의 인터페이스를 설정합니다.

내가 아직 놓치고 있는 다른 방법들이 많이 있을 거야

가장 쉬운 방법은 이 제품을 사용하는 것 같습니다.ThreadPoolExecutor

  1. 큐가 있으며 병렬로 작동해야 하는 스레드 수를 설정할 수 있습니다.
  2. 콜백 방식은 다음과 같습니다.

후크 방식

는 protected 합니다.beforeExecute(java.lang.Thread, java.lang.Runnable) ★★★★★★★★★★★★★★★★★」afterExecute(java.lang.Runnable, java.lang.Throwable)각 태스크 실행 전후에 호출되는 메서드.예를 들어 ThreadLocal 재초기화, 통계 수집, 로그 항목 추가 등 실행 환경을 조작하는 데 사용할 수 있습니다. 방법 「」, 「」도 .terminated()실행자가 완전히 종료된 후 수행해야 하는 특별한 처리를 수행하도록 덮어쓸 수 있습니다.

우선은 우선입니다.afterExecute()후 "콜백"이 됩니다.terminated()모든 스레드가 언제 완료되었는지 알 수 있습니다.

그래서 당신이 해야 할 일은 다음과 같다.

  1. 실행자를 만듭니다.

    private ThreadPoolExecutor executor;
    private int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();    
    
    
    
    private void initExecutor() {
    
    executor = new ThreadPoolExecutor(
            NUMBER_OF_CORES * 2,  //core pool size
            NUMBER_OF_CORES * 2, //max pool size
            60L, //keep aive time
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>()
    ) {
    
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);
                //Yet another thread is finished:
                informUiAboutProgress(executor.getCompletedTaskCount(), listOfUrisToProcess.size());
            }
        }
    
    };
    
        @Override
        protected void terminated() {
            super.terminated();
            informUiThatWeAreDone();
        }
    
    }
    
  2. 스레드 시작:

    private void startTheWork(){
        for (Uri uri : listOfUrisToProcess) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    doSomeHeavyWork(uri);
                }
            });
        }
        executor.shutdown(); //call it when you won't add jobs anymore 
    }
    

메서드 「」informUiThatWeAreDone();모든 스레드가 완료되면 UI 업데이트 등 필요한 작업을 수행합니다.

주의: 잊지 말고synchronized.synchronized 사람의 synchronized이것로 이어집니다.

이게 도움이 됐으면 좋겠네요!

여기 간단하고, 짧고, 이해하기 쉽고, 나에게 딱 맞는 솔루션이 있습니다.다른 스레드가 끝날 때 화면을 그려야 했지만 메인 스레드가 화면을 제어하기 때문에 그릴 수 없었습니다.그래서:

(1) (1)을 만들었습니다.boolean end1 = false;사실대로 말하다이는 메인 스레드에서 "지연 후" 루프를 통해 픽업되며, 여기서 응답됩니다.

(2) 내 스레드는 다음을 포함한다.

void myThread() {
    end1 = false;
    new CountDownTimer(((60000, 1000) { // milliseconds for onFinish, onTick
        public void onFinish()
        {
            // do stuff here once at end of time.
            end1 = true; // signal that the thread has ended.
        }
        public void onTick(long millisUntilFinished)
        {
          // do stuff here repeatedly.
        }
    }.start();

}

(3) 다행히 "post Delayed"는 메인 스레드에서 실행되므로 거기서 1초에 1회 다른 스레드를 체크합니다.다른 스레드가 끝나면 다음에 하고 싶은 모든 작업을 시작할 수 있습니다.

Handler h1 = new Handler();

private void checkThread() {
   h1.postDelayed(new Runnable() {
      public void run() {
         if (end1)
            // resond to the second thread ending here.
         else
            h1.postDelayed(this, 1000);
      }
   }, 1000);
}

(4) 마지막으로, 다음과 같이 전화하여 코드의 어딘가에서 실행되는 모든 것을 시작합니다.

void startThread()
{
   myThread();
   checkThread();
}

속성 변경 지원이 내장된 SwingWorker를 사용할 수도 있습니다.상태 변경 리스너 예에 대해서는 addPropertyChangeListener() 또는 get() 메서드를 참조하십시오.

스레드 클래스에 대한 Java 문서를 참조하십시오.스레드 상태를 확인할 수 있습니다.3개의 스레드를 멤버 변수에 넣으면 3개의 스레드 모두 서로의 상태를 읽을 수 있습니다.

그러나 스레드 사이에 레이스 상태가 발생할 수 있기 때문에 조금 주의해야 합니다.다른 스레드 상태에 근거한 복잡한 논리는 피하도록 하세요.여러 스레드가 같은 변수에 쓰이지 않도록 하십시오.

언급URL : https://stackoverflow.com/questions/702415/how-to-know-if-other-threads-have-finished

반응형