[java] 동일한 스레드에서 start 메서드를 두 번 호출하는 것이 합법적입니까?

다음 코드는 프로그램에서 두 번째로 메서드를 java.lang.IllegalThreadStateException: Thread already started호출 할 때 연결됩니다 .start()

updateUI.join();

if (!updateUI.isAlive())
    updateUI.start();

이것은 일 두 번째 시간 updateUI.start()이라고합니다. 나는 그것을 여러 번 밟았고 스레드가 호출되고 updateUI.start().

호출 updateUI.run()은 오류를 피하지만 스레드가 UI 스레드 (SO의 다른 게시물에서 언급 한 호출 스레드)에서 실행되도록합니다. 이것은 내가 원하는 것이 아닙니다.

스레드 한 번만 시작할 수 있습니까 ? 그렇다면 스레드를 다시 실행하려면 어떻게해야합니까? 이 특정 스레드는 UI 스레드에서 수행 한 것보다 스레드에서 수행하지 않고 사용자가 비합리적으로 오래 기다릴 경우 백그라운드에서 계산을 수행합니다.



답변

로부터 자바 API 사양 에 대한 Thread.start방법 :

스레드를 두 번 이상 시작하는 것은 결코 합법적이지 않습니다. 특히 스레드가 실행을 완료 한 후에는 다시 시작할 수 없습니다.

더욱이:

오류 :
IllegalThreadStateException-스레드가 이미 시작된 경우.

예, a Thread는 한 번만 시작할 수 있습니다.

그렇다면 스레드를 다시 실행하려면 어떻게해야합니까?

Thread두 번 이상 실행해야하는 경우의 새 인스턴스를 Thread만들고 호출 start해야합니다.


답변

맞습니다. 문서에서 :

스레드를 두 번 이상 시작하는 것은 결코 합법적이지 않습니다. 특히 스레드가 실행을 완료 한 후에는 다시 시작할 수 없습니다.

반복 계산을 위해 무엇을 할 수 있는지에 관해서는 SwingUtilities invokeLater 메소드를 사용할 수있는 것처럼 보입니다 . 이미 run()직접 호출을 실험하고 있습니다. 즉 Runnable, raw가 아닌 ​​a 사용에 대해 이미 생각하고 Thread있습니다. 작업 invokeLater에만 방법을 사용 해보고 Runnable그것이 당신의 정신 패턴에 조금 더 잘 맞는지 확인하십시오.

다음은 문서의 예입니다.

 Runnable doHelloWorld = new Runnable() {
     public void run() {
         // Put your UI update computations in here.
         // BTW - remember to restrict Swing calls to the AWT Event thread.
         System.out.println("Hello World on " + Thread.currentThread());
     }
 };

 SwingUtilities.invokeLater(doHelloWorld);
 System.out.println("This might well be displayed before the other message.");

해당 println호출을 계산으로 대체하면 정확히 필요한 것일 수 있습니다.

편집 : 댓글에 대한 후속 조치로 원본 게시물에서 Android 태그를 발견하지 못했습니다. Android 작업에서 invokeLater에 해당하는 것은 Handler.post(Runnable). javadoc에서 :

/**
 * Causes the Runnable r to be added to the message queue.
 * The runnable will be run on the thread to which this handler is
 * attached.
 *
 * @param r The Runnable that will be executed.
 *
 * @return Returns true if the Runnable was successfully placed in to the
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.
 */

따라서 Android 세계에서는 위와 동일한 예제를 사용하여 Swingutilities.invokeLaterHandler.


답변

방금 도착한 답변은 자신이하는 일을하지 말아야하는 이유를 다룹니다. 실제 문제를 해결하기위한 몇 가지 옵션이 있습니다.

이 특정 스레드는 UI 스레드에서 수행 한 것보다 스레드에서 수행하지 않고 사용자가 비합리적으로 오래 기다릴 경우 백그라운드에서 계산을 수행합니다.

자신의 스레드를 덤프하고 AsyncTask.

또는 필요할 때 새 스레드를 만듭니다.

또는 스레드를 LinkedBlockingQueue다시 시작하지 않고 작업 대기열 (예 :)에서 작동하도록 스레드를 설정합니다 .


답변

아니요 , Thread를 다시 시작할 수 없습니다. 그렇게하면 runtimeException java.lang.IllegalThreadStateException이 발생합니다. >

그 이유는 일단 run () 메소드가 Thread에 의해 실행되면 죽은 상태가되기 때문입니다.

예를 들어 보겠습니다. 스레드를 다시 시작하고 그것에 start () 메서드를 호출하는 것 (내부적으로 run () 메서드를 호출 할 것임)을 호출하는 것은 죽은 사람에게 깨어나 실행하도록 요청하는 것과 같습니다. 그의 인생을 마친 후 사람은 죽은 상태로 이동합니다.

public class MyClass implements Runnable{

    @Override
    public void run() {
           System.out.println("in run() method, method completed.");
    }

    public static void main(String[] args) {
                  MyClass obj=new MyClass();
        Thread thread1=new Thread(obj,"Thread-1");
        thread1.start();
        thread1.start(); //will throw java.lang.IllegalThreadStateException at runtime
    }

}

/ * run () 메소드의 OUTPUT, 메소드 완료. 스레드 “main”의 예외 java.lang.IllegalThreadStateException at java.lang.Thread.start (Unknown Source) * /

이것을 확인


답변

해야 할 일은 Runnable을 만들고 Runnable을 실행할 때마다 새 Thread로 래핑하는 것입니다. 정말 추한 일이지만 다른 스레드로 스레드를 래핑하여 코드를 다시 실행할 수 있지만이 작업 만 수행하면됩니다.


답변

말했듯이 스레드는 두 번 이상 시작할 수 없습니다.

말의 입에서 바로 : Java API 사양

스레드를 두 번 이상 시작하는 것은 결코 합법적이지 않습니다. 특히 스레드가 실행을 완료 한 후에는 다시 시작할 수 없습니다.

스레드에서 진행중인 모든 작업을 다시 실행해야하는 경우 새 스레드를 만들고 실행해야합니다.


답변

스레드를 재사용하는 것은 Java API에서 불법 행위입니다. 그러나 실행 가능한 구현으로 래핑하고 해당 인스턴스를 다시 실행할 수 있습니다.