2011-01-21 3 views
3

Java 및 App Server 사용 스레드 실행기가있는 응용 프로그램을 배포합니다.종료 후 Thread Executer 자체가 메모리에 남아있는 이유는 무엇입니까?

배포가 진행되지 않는 동안 나는 executer를 종료하도록 요청합니다. 이렇게하면 모든 작업이 성공적으로 취소됩니다. 그러나 VisualVM을 통해 나는 executer 자체를 나타내는 스레드를 볼 수 있으며 wait 상태에 있습니다. 나는 전체 애플리케이션이 배포 해제 될 때 임원에 대한 언급을 유지하지 않는다. 따라서 배포 - 배포 취소주기를 여러 번 반복하면 스레드 수가 증가하는 방식을 볼 수 있습니다.

어떻게 제거합니까?

UPDATE :

public void startScheduler() 
{ 
    if (scheduledExecutor == null) 
    { 
     scheduledExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("My ScheduledExecutor")); 
     processFuture = scheduledExecutor.scheduleAtFixedRate(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        startProcessor(); 
       } 
      }, 0, 84600, TimeUnit.SECONDS); 
    } 
} 


public void stopScheduler() 
{ 

    if (processFuture != null) 
    { 
     processFuture.cancel(true); 
     processFuture = null; 
    } 

    if (scheduledExecutor != null) 
    { 
     try 
     { 
      scheduledExecutor.shutdownNow(); 
      scheduledExecutor.awaitTermination(10, TimeUnit.SECONDS); 
     } 
     catch (InterruptedException ignored) 
     {} 
     finally 
     { 
      scheduledExecutor = null; 
     } 
    } 

} 
+2

사용하는 특정 Executor 클래스는 무엇입니까? 그리고 당신이 부르는 정확한 종료 방법은 무엇입니까? – richs

+0

Executors.newSingleThreadScheduledExecutor 및 shutdownNow() – user567068

+0

이 코드는 정확합니다. 집행자가 종료되면 문제는 다른 곳에 있습니다. – jtahlborn

답변

2

당신이 "는 실행자 자체를 나타내는 스레드"로 무슨 뜻인지 자세히 설명해 수 : 여기

코드 예제

는 코드입니다. 이름/ID/스레드 그룹이란 무엇입니까? 나는 집행자 서비스가 그러한 스레드를 생성한다고 생각하지 않습니다.

실행자는 새 스레드를 생성합니다 (구성 가능한 ThreadFactory 사용). Thread는 부모의 일부 속성, 즉 Thread.currentThread()를 자동으로 상속받습니다. 그러나 배포/배포 해제 사이클이있는 웹 응용 프로그램 시나리오에서이 문제의 가장 문제가되는 부분은 스레드의 ContextClassLoader이며 부모 스레드에서 상속됩니다. ContextClassLoader가 웹 응용 프로그램 아카이브의 클래스를 보유하고 있으면 생성 된 Executors Thread는이 ClassLoader에 대한 참조도 갖습니다. 실행자에 의해 실행되는 코드가 예를 들어, WebappClassLoader 클래스의 ThreadLocals를 사용하면 ClassLoader 누수 문제가 발생할 수 있습니다.

+0

가 코드를 업데이트했습니다. startScheduler()는 배포 할 때 호출되고, unServlet()은 배포를 취소 할 때 호출됩니다. VisualVM에서 "My ScheduledExecutor"스레드를 참조하십시오. 컨테이너의 책임을 일부 담당하는 집에서 만든 앱 로더를 사용하기 때문에 당신이 옳을 것이라고 생각합니다. 일종의 누수입니다. (예 : 클래스로드). 종료 코드가 올바르게 보이나요? 아니면 CalssLoader에 대한 참조를 어떻게 든 등록 취소하는 것처럼 할 수있는 다른 것이 있습니다 ... 감사합니다! – user567068

+0

실행 코드가 좋게 보입니다. 테스트 케이스로 확인했습니다.누수를 찾으려면 많은 재배포를 수행하고 힙 덤프를 가져옵니다. 그런 다음 모든 스레드 ("My ScheduledExecutor") 객체에서 GC 루트에 대한 경로를 찾습니다. WebappClassLoaders를 찾을 수있을 것입니다. Eclipse MAT와 "Class By Loader"를 사용하십시오. – mhaller

1

Executor를 shutdown 메서드를 사용하여 명시 적으로 중지해야합니다. 그렇지 않으면 발견 한 것처럼 멈추게됩니다. Executors.newSingleThreadExecutor에 대한 javadoc에서 작업자 스레드가 포함 된 것을 볼 수 있습니다.

shutdownNow의를위한 JavaDoc 말한다 : 보장이 최선의 노력이 작업을 실행 적극적으로 처리를 중지하려고 시도합니다 이상이 없습니다

. 예를 들어, 통상의 구현은 Thread.interrupt()를 개입시켜 취소하므로, 태스크가 마스크를 붙일 지, 인터럽트에 응답하지 않는 경우, 태스크는 종료하지 않습니다.

실행중인 작업이 인터럽트에 응답하지 않으면 (나가는 일없이 InterruptedExceptions을 감추는) 실행 프로그램이 종료되지 않습니다. 명시 적으로 종료하지 않는 데몬이 아닌 모든 스레드는 중단되어 JVM이 종료되지 않도록합니다. 디버깅하는 것이 재미있을 수 있습니다.

+0

shutdownNow를 사용하고 잠시 기다려주십시오 ... – user567068

+0

응용 프로그램을 배포 해제 할 때까지는 스레드가 대기 상태에 있으므로 InterruptedExceptions가 "삼키는"것이므로 적절히 방지 할 수 있습니다 닥쳐. – user567068

관련 문제