현재 Java로 실행중인 모든 스레드 목록을 가져옵니다.


232

현재 JVM에서 실행중인 모든 스레드 목록을 얻을 수있는 방법이 있습니까 (클래스에서 시작 하지 않은 스레드 포함 )?

목록에서 모든 스레드 의 ThreadClass객체 를 가져올 수도 있습니까?

코드를 통해이 작업을 수행 할 수 있기를 원합니다.

답변:


325

반복 가능한 세트를 얻으려면 :

Set<Thread> threadSet = Thread.getAllStackTraces().keySet();

19
제안 된 다른 대안보다 훨씬 깨끗하지만 모든 스레드에 대해 스택 추적을 얻는 비용이 발생한다는 단점이 있습니다. 어쨌든 이러한 스택 추적을 사용하는 경우 이는 분명히 우수합니다. 그렇지 않으면 깨끗한 코드 이외의 게인이 없으면 속도가 크게 느려질 수 있습니다.
Eddie

29
@ 에디 그것은 상식에서 가정입니까, 아니면 실험을 했습니까? "상당히 느리다"고 말합니다. 얼마나 느려? 그만한 가치가 있습니까? 효율성을 위해 코드를 더 악화시키려는 시도에 의문을 제기합니다. 효율성 요구 사항 효율성을 정량적으로 측정 할 수있는 인프라 가 있다면 코드를 악화시키는 사람들이하는 일에 대해 잘 알고 있습니다. Donald Knuth에 따르면 모든 악의 근원을 보십시오 .
thejoshwolfe

20
나는 이러한 특정 대안을 시간 지정하지는 않았지만 스택 추적을 수집하는 스레드와 다른 Java 방법을 사용했습니다. 성능에 미치는 영향은 사용중인 JVM (예 : JRockit 및 Sun JVM)에 따라 크게 달라집니다. 특정 인스턴스에서 측정 할 가치가 있습니다. 그것이 당신에게 영향을 미치는지 아닌지는 JVM 선택과 가지고있는 스레드 수에 달려 있습니다. 약 250 개의 스레드에 대해 ThreadMXBean.dumpAllThreads를 통해 모든 스택 추적을 가져 오는 데 150-200 msec가 걸리고 (트레이스가없는) 스레드 목록 만 측정 할 수는 없습니다 (0 msec).
Eddie

4
내 시스템 (Oracle Java 1.7 VM)에서 빠른 검사는이 방법이 아래 대안보다 ~ 70..80 배 느리다는 것을 보여줍니다. 스택 추적 및 리플렉션은 가장 무거운 Java 작업에 속합니다.
Franz D.

5
@thejoshwolfe : 물론 가독성은 중요한 요소이며, 마이크로 최적화 등을하지 않아야합니다. 그러나 작은 응용 프로그램 성능 모니터를 작성하는 동안 연구를 수행했습니다. 이러한 종류의 도구의 경우 신뢰할 수있는 데이터를 얻으려면 최소한의 성능 표시가 필요하므로 stacktrace-less 방법을 선택했습니다.
Franz D.

75

다음 ThreadGroup과 같이 루트에 대한 핸들을 가져옵니다 .

ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
ThreadGroup parentGroup;
while ((parentGroup = rootGroup.getParent()) != null) {
    rootGroup = parentGroup;
}

이제 enumerate()루트 그룹 의 함수를 반복해서 호출하십시오 . 두 번째 인수를 사용하면 모든 스레드를 재귀 적으로 얻을 수 있습니다.

Thread[] threads = new Thread[rootGroup.activeCount()];
while (rootGroup.enumerate(threads, true ) == threads.length) {
    threads = new Thread[threads.length * 2];
}

배열이 모든 항목을 포함하기에 충분히 클 때까지 enumerate ()를 반복적으로 호출하는 방법에 유의하십시오.


22
이 전략이 인터넷에서 인기가 있다는 사실에 놀랐습니다. 내 전략 은 훨씬 간단하고 (한 줄의 코드) 경쟁 조건을 피하는 추가 보너스와 함께 작동합니다.
thejoshwolfe

11
@ thejoshwolfe : 사실, 나는 동의합니다-귀하의 답변이 훨씬 낫다고 생각합니다 .1 년이 늦지 않았다면 아마도 대답이 처음에 받아 들여졌을 것입니다. OP가 여전히 자주하는 SO를 자주 사용한다면 내 대답을 받아들이지 않고 오히려 당신의 것을 받아들이는 것이 좋습니다.
Frerich Raabe

2
이외의 다른 경우에는 rootGroup을 사용해야합니다 new Thread[rootGroup.activeCount()+1]. activeCount()0이면 무한 루프에 빠질 것입니다.
jmiserez

7
@ thejoshwolfe 나는이 솔루션이 훨씬 저렴하다고 가정합니다.
Haozhun

19
IMHO 모니터링 목적에 훨씬 적합하므로이 과소 평가 된 결과에 +1합니다. 고유 한 경쟁 조건은 모니터링에서 중요하지 않습니다. 그러나 일부 빠른 '더티 테스트'에서 알 수 있듯이 스택 트레이스 기반 솔루션보다 약 70-80 배 빠릅니다. 모니터링을 위해서는 모니터링되는 시스템에 미치는 영향을 가능한 한 작게 유지하기 위해 작은 성능 저하가 필수적입니다 (Heisenberg가 다시 발생합니다).보다 안정적인 정보가 필요할 수있는 디버깅의 경우 stacktrace 방법은 다음과 같습니다. 본질적인. BTW, MxBean 솔루션은 stacktrace를 사용하는 것보다 훨씬 느립니다.
Franz D.

29

예, 스레드 목록을 확인하십시오 . 해당 페이지에 많은 예제가 있습니다.

프로그래밍 방식으로 수행해야합니다. 적어도 Linux에서 목록을 원한다면 다음 명령을 사용할 수 있습니다.

kill -3 processid

VM은 stdout에 스레드 덤프를 수행합니다.


5
-3을 죽입니까? 적어도 내 리눅스에서는 "터미널 종료"입니다. 죽이고, 나열하지 않습니다.
Michael H.

5
cletus는 실제로 정확합니다. kill -3은 신호의 의미에 관계없이 stdout에 덤프를 스레드합니다. 대신 jstack을 사용하는 것이 좋습니다.
Dan Hardiker

스레드 목록에 도달 할 수 없음 : nadeausoftware.com이 연결을 거부했습니다.
DSlomer64


14

jconsole을 살펴 보셨습니까 ?

특정 Java 프로세스에 대해 실행중인 모든 스레드가 나열됩니다.

JDK bin 폴더에서 jconsole을 시작할 수 있습니다.

Ctrl+BreakWindows에서 충돌 하거나 kill pid --QUITLinux에서 전송 하여 모든 스레드에 대한 전체 스택 추적을 얻을 수도 있습니다 .


Java 클래스 내 목록에 액세스하고 싶습니다
Kryten

어떤 경우에 클레 투스의 대답을보십시오.
pjp

3
음, 왜 사람들이 프로그래밍 방식 솔루션을 원한다고 말했을 때 사람들이 이것을 투표합니까?
cletus

질문에 그 내용이 나와 있지 않기 때문입니다. 명시 적으로 보이도록 질문을 편집하겠습니다.
pjp

8

Apache Commons 사용자는을 사용할 수 있습니다 ThreadUtils. 현재 구현에서는 이전에 설명한 스레드 그룹 접근 방식을 사용합니다.

for (Thread t : ThreadUtils.getAllThreads()) {
      System.out.println(t.getName() + ", " + t.isDaemon());
}

7

다음과 같이 시도해보십시오.

Thread.getAllStackTraces().keySet().forEach((t) -> System.out.println(t.getName() + "\nIs Daemon " + t.isDaemon() + "\nIs Alive " + t.isAlive()));

필요한 경우 더 많은 스레드 특성을 얻을 수 있습니다.


5

Groovy 에서는 개인 메소드를 호출 할 수 있습니다

// Get a snapshot of the list of all threads 
Thread[] threads = Thread.getThreads()

Java 에서는 보안 관리자가 허용하는 경우 리플렉션을 사용하여 해당 메소드를 호출 할 수 있습니다.


스레드에 대해 getThreads가 정의되어 있지 않습니다. 그리고 나는 문서 에서이 기능을 보지 못했습니다.

4

메인 스레드에서 시작한 스레드 목록을 가져 오는 코드 스 니펫 :

import java.util.Set;

public class ThreadSet {
    public static void main(String args[]) throws Exception{
        Thread.currentThread().setName("ThreadSet");
        for ( int i=0; i< 3; i++){
            Thread t = new Thread(new MyThread());
            t.setName("MyThread:"+i);
            t.start();
        }
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        for ( Thread t : threadSet){
            if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup()){
                System.out.println("Thread :"+t+":"+"state:"+t.getState());
            }
        }
    }
}

class MyThread implements Runnable{
    public void run(){
        try{
            Thread.sleep(5000);
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

산출:

Thread :Thread[MyThread:2,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:0,5,main]:state:TIMED_WAITING
Thread :Thread[MyThread:1,5,main]:state:TIMED_WAITING
Thread :Thread[ThreadSet,5,main]:state:RUNNABLE

프로그램에서 시작하지 않은 시스템 스레드를 포함한 모든 스레드가 필요한 경우 아래 조건을 제거하십시오.

if ( t.getThreadGroup() == Thread.currentThread().getThreadGroup())

이제 출력 :

Thread :Thread[MyThread:2,5,main]:state:TIMED_WAITING
Thread :Thread[Reference Handler,10,system]:state:WAITING
Thread :Thread[MyThread:1,5,main]:state:TIMED_WAITING
Thread :Thread[ThreadSet,5,main]:state:RUNNABLE
Thread :Thread[MyThread:0,5,main]:state:TIMED_WAITING
Thread :Thread[Finalizer,8,system]:state:WAITING
Thread :Thread[Signal Dispatcher,9,system]:state:RUNNABLE
Thread :Thread[Attach Listener,5,system]:state:RUNNABLE

3
    public static void main(String[] args) {


        // Walk up all the way to the root thread group
        ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
        ThreadGroup parent;
        while ((parent = rootGroup.getParent()) != null) {
            rootGroup = parent;
        }

        listThreads(rootGroup, "");
    }


    // List all threads and recursively list all subgroup
    public static void listThreads(ThreadGroup group, String indent) {
        System.out.println(indent + "Group[" + group.getName() + 
                ":" + group.getClass()+"]");
        int nt = group.activeCount();
        Thread[] threads = new Thread[nt*2 + 10]; //nt is not accurate
        nt = group.enumerate(threads, false);

        // List every thread in the group
        for (int i=0; i<nt; i++) {
            Thread t = threads[i];
            System.out.println(indent + "  Thread[" + t.getName() 
                    + ":" + t.getClass() + "]");
        }

        // Recursively list all subgroups
        int ng = group.activeGroupCount();
        ThreadGroup[] groups = new ThreadGroup[ng*2 + 10];
        ng = group.enumerate(groups, false);

        for (int i=0; i<ng; i++) {
            listThreads(groups[i], indent + "  ");
        }
    }

3

자바 콘솔에서 Ctrl-Break를 누르십시오 . 모든 스레드와 힙에 대한 정보가 나열됩니다. 이것은 물론 개체에 대한 액세스 권한을 부여하지 않습니다. 그러나 어쨌든 디버깅에 매우 도움이 될 수 있습니다.


1

터미널을 사용하여 스레드 및 전체 상태 목록을 얻으려면 아래 명령을 사용할 수 있습니다.

jstack -l <PID>

어떤 PID는 컴퓨터에서 실행중인 프로세스의 ID입니다. Java 프로세스의 프로세스 ID를 얻으려면 jps명령을 실행하면 됩니다.

또한 fastthread 또는 spotify thread analyzer 도구 와 같은 TDA (Thread Dump Analyzer)에서 jstack에 의해 생성 된 스레드 덤프를 분석 할 수 있습니다 .


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.