Get Thread by Name in Java
1. 개요
스레드는 Java에서 동시 프로그래밍의 기본 빌딩 블록입니다. 많은 애플리케이션에서 디버깅, 모니터링 또는 스레드의 상태와의 상호작용과 같은 작업을 수행하기 위해 특정 스레드를 이름으로 찾아야 할 때가 있습니다.
이 튜토리얼에서는 Java에서 이름으로 스레드를 검색하는 방법을 탐구할 것입니다.
2. Java에서 스레드 이름 이해하기
각 스레드는 실행 중에 고유한 이름은 스레드를 자동으로 이름을 부여하지만(예: Thread-0, Thread-1 등), 추적성을 높이기 위해 스레드에 사용자 정의 이름을 부여할 수 있습니다:
Thread¨NBSP;customThread = new Thread(() -> {
log.info("Running custom thread");
}, "MyCustomThread");
customThread.start();
이 스레드의 이름은 MyCustomThread로 설정됩니다.
다음으로, 이름으로 스레드를 가져오는 방법을 탐구해 보겠습니다.
3. Thread.getAllStackTraces() 사용하기
Thread.getAllStackTraces() 메서드는 모든 활성 스레드와 해당 스택 트레이스를 포함하는 맵을 제공합니다. 이 맵을 통해 모든 활성 스레드를 반복하며 특정 스레드를 이름으로 검색할 수 있습니다.
이 방법을 사용하는 방법은 다음과 같습니다:
public static Thread getThreadByName(String name) {
return Thread.getAllStackTraces()
.keySet()
.stream()
.filter(thread -> thread.getName().equals(name))
.findFirst()
.orElse(null); // 스레드를 찾지 못한 경우 null 반환
}
이 메서드에서 하는 작업의 세부 사항은 다음과 같습니다:
- Thread.getAllStackTraces() 메서드는 모든 활성 스레드의 Map
를 반환합니다. - 우리는 Java의 Stream API를 사용하여 편리하게 처리를 위해 stream() 메서드를 사용하고, 입력과 일치하는 이름을 가진 스레드만 포함하도록 스트림을 필터링합니다.
- 일치하는 항목이 발견되면 해당 스레드를 반환하고, 그렇지 않으면 null을 반환합니다.
이 메서드를 단위 테스트로 검증해 보겠습니다:
@Test
public void givenThreadName_whenUsingGetAllStackTraces_thenThreadFound() throws InterruptedException {
Thread testThread = new Thread(() -> {
try {
Thread.sleep(1000); // 작업 시뮬레이션
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "TestThread");
testThread.start();
Thread foundThread = ThreadFinder.getThreadByName("TestThread");
assertNotNull(foundThread);
assertEquals("TestThread", foundThread.getName());
testThread.join(); // 스레드가 종료되도록 보장
}
테스트의 주요 포인트는 다음과 같습니다:
- 스레드 생성: 이름이 TestThread인 스레드를 생성하여 잠깐 동안 sleep하여 작업을 시뮬레이션합니다.
- Assertions: 주어진 이름의 스레드가 각 메서드를 사용하여 발견되었는지 확인하고 이름을 검증합니다.
- 스레드 조인: 마지막으로, 생성된 스레드가 join()으로 종료되도록 하여 남아 있는 스레드가 없도록 합니다.
4. ThreadGroup 사용하기
ThreadGroup 클래스는 이름으로 스레드를 찾는 또 다른 옵션입니다. A ThreadGroup는 스레드 그룹을 나타내며, 이를 집합 Entity로서 관리하거나 검사할 수 있게 합니다. 특정 스레드 그룹을 쿼리하여 이름으로 스레드를 찾을 수 있습니다.
ThreadGroup에 접근하는 방법은 여러 가지가 있습니다:
- 현재 ThreadGroup을 Thread.currentThread().getThreadGroup()로 가져오기
- new ThreadGroup(name)으로 새 ThreadGroup 생성하기
- 부모 참조를 통해 루트 그룹으로 이동하기
여기 ThreadGroup을 사용한 솔루션이 있습니다:
public static Thread getThreadByThreadGroupAndName(ThreadGroup threadGroup, String name) {
Thread[] threads = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threads);
for (Thread thread : threads) {
if (thread != null && thread.getName().equals(name)) {
return thread;
}
}
return null; // 스레드를 찾지 못한 경우
}
이 솔루션에서 우리가 하는 작업은 다음과 같습니다:
- activeCount() 메서드는 스레드 그룹의 활성 스레드 수를 추정합니다.
- enumerate() 메서드는 모든 활성 스레드를 포함하는 배열을 채웁니다.
- 우리는 배열을 반복하여 원하는 이름과 일치하는 스레드를 찾고 반환합니다.
- 일치하는 항목이 발견되지 않으면 null을 반환합니다.
이 메서드에 대한 단위 테스트도 작성해 보겠습니다:
@Test
public void givenThreadName_whenUsingThreadGroup_thenThreadFound() throws InterruptedException {
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
Thread testThread = new Thread(threadGroup, () -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "TestThread");
testThread.start();
Thread foundThread = ThreadFinder.getThreadByThreadGroupAndName(threadGroup, "TestThread");
assertNotNull(foundThread);
assertEquals("TestThread", foundThread.getName());
testThread.join();
}
5. 결론
이 기사에서는 Java에서 이름으로 스레드를 가져오는 두 가지 방법을 살펴보았습니다. Thread.getAllStackTraces() 메서드는 더 간단하지만 스코프 없이 모든 스레드를 가져오며, ThreadGroup 방식은 특정 스레드 그룹에 대해 더 많은 제어를 제공합니다.
이 튜토리얼의 예제 코드는 GitHub에서 확인할 수 있습니다.