[java] Java Thread Garbage 수집 여부

이 질문은 일부 사이트에 게시되었습니다. 거기에서 정답을 찾지 못해서 다시 여기에 게시하겠습니다.

public class TestThread {
    public static void main(String[] s) {
        // anonymous class extends Thread
        Thread t = new Thread() {
            public void run() {
                // infinite loop
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    // as long as this line printed out, you know it is alive.
                    System.out.println("thread is running...");
                }
            }
        };
        t.start(); // Line A
        t = null; // Line B
        // no more references for Thread t
        // another infinite loop
        while (true) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
            }
            System.gc();
            System.out.println("Executed System.gc()");
        } // The program will run forever until you use ^C to stop it
    }
}

내 질문은 스레드 중지에 관한 것이 아닙니다. 내 질문을 다시 말하겠습니다. 라인 A (위의 코드 참조)는 새 스레드를 시작합니다. 라인 B는 스레드 참조를 null로 만듭니다. 따라서 JVM에는 이제 참조가없는 스레드 개체 (실행 중 상태)가 있습니다 (줄 B의 t = null). 그래서 내 질문은 왜이 스레드 (주 스레드에 더 이상 참조가 없음)가 주 스레드가 실행될 때까지 계속 실행됩니까? 내 이해에 따르면 스레드 개체는 라인 B 이후에 가비지 수집되어야합니다.이 코드를 5 분 이상 실행하여 Java 런타임에 GC를 실행하도록 요청했지만 스레드가 멈추지 않습니다.

이번에는 코드와 질문이 모두 명확하기를 바랍니다.



답변

실행중인 스레드는 소위 가비지 콜렉션 루트로 간주되며 가비지 콜렉션되지 않도록하는 것 중 하나입니다. 가비지 수집기가 개체가 ‘ 도달 할 수 있는지’여부를 결정할 때 항상 가비지 수집기 루트 집합을 참조 지점으로 사용합니다.

이것을 고려하십시오. 왜 메인 스레드가 가비지 수집되지 않고 아무도 그 스레드를 참조하지 않습니다.


답변

설명했듯이 실행중인 스레드는 정의에 따라 GC에 영향을받지 않습니다. GC는 항상 도달 가능한 것으로 간주되는 “루트”를 스캔하여 작업을 시작합니다. 루트는 전역 변수 (Java-talk의 “정적 필드”)와 실행중인 모든 스레드의 스택 (실행중인 스레드의 스택이 해당 Thread인스턴스를 참조한다고 상상할 수 있음 )을 포함합니다.

그러나 스레드를 “데몬”스레드로 만들 수 있습니다 (참조 Thread.setDaemon(boolean)). 데몬 스레드는 데몬이 아닌 스레드보다 더 이상 가비지 수집되지 않지만 실행중인 모든 스레드가 데몬이면 JVM이 종료됩니다. 이를 상상하는 한 가지 방법은 모든 스레드가 종료 될 때 데몬이 아닌 실행 스레드가 남아 있는지 확인하는 것입니다. 그렇지 않은 경우 종료 스레드 System.exit()는 JVM을 종료 하는 호출을 강제 실행합니다 (실행중인 데몬 스레드 종료). 이것은 GC 관련 문제가 아닙니다. 어떤 방식으로 스레드는 수동으로 할당됩니다. 그러나 이것이 JVM이 세미 로그 스레드를 허용하는 방법입니다. 일반적으로 Timer인스턴스에 사용됩니다 .


답변

JVM에는 실행중인 모든 스레드에 대한 참조가 있습니다.

스레드 (또는 참조하는 것)는 실행중인 동안 가비지 수집되지 않습니다.


답변

스레드는 볼 수없는 스레드에 대한 참조가 있기 때문에 가비지 수집되지 않습니다. 예를 들어 런타임 시스템에는 참조가 있습니다.

스레드가 생성되면 현재 스레드 그룹에 추가됩니다. 현재 스레드 그룹의 스레드 목록을 가져올 수 있으므로 참조를 얻는 또 다른 방법입니다.


답변