Java

[Java] μŠ€λ ˆλ“œμ˜ κΈ°λŠ₯κ³Ό 디버깅

9taetae9 2025. 2. 6. 11:45
728x90

1. λ©€ν‹°μŠ€λ ˆλ”©μ˜ κ°œλ…

λ©€ν‹°μŠ€λ ˆλ”©μ€ ν•˜λ‚˜μ˜ ν”„λ‘œκ·Έλž¨ λ‚΄μ—μ„œ μ—¬λŸ¬ μž‘μ—…μ„ λ™μ‹œμ— μ‹€ν–‰ν•  수 μžˆλ„λ‘ ν•˜λŠ” 기법이닀. Javaμ—μ„œλŠ” Thread ν΄λž˜μŠ€μ™€ Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ΄μš©ν•΄ λ©€ν‹°μŠ€λ ˆλ“œλ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.
μŠ€λ ˆλ“œλ₯Ό ν™œμš©ν•˜λ©΄ CPU μžμ›μ„ 보닀 효율적으둜 μ‚¬μš©ν•˜μ—¬ 병렬 처리 및 응닡성을 높일 수 μžˆλ‹€.


2. μƒˆλ‘œμš΄ μŠ€λ ˆλ“œ μƒμ„±ν•˜κΈ°

Javaμ—μ„œ μƒˆλ‘œμš΄ μŠ€λ ˆλ“œλ₯Ό μƒμ„±ν•˜λ €λ©΄ λ¨Όμ € Thread 객체λ₯Ό 생성해야 ν•œλ‹€. μƒμ„±μžμ— Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 객체λ₯Ό μ „λ‹¬ν•˜κ³ , Runnable μΈν„°νŽ˜μ΄μŠ€μ˜ run() λ©”μ„œλ“œμ— μŠ€λ ˆλ“œκ°€ μ‹€ν–‰ν•  λ‘œμ§μ„ μž‘μ„±ν•  수 μžˆλ‹€.

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        // μš΄μ˜μ²΄μ œμ— μ˜ν•΄ μŠ€μΌ€μ€„ 되면 ν•΄λ‹Ή μŠ€λ ˆλ“œμ—μ„œ 싀행될 둜직
        System.out.println("run() 호좜 : " + Thread.currentThread().getName());
        System.out.println("Thread.currentThread().getPriority() = " + Thread.currentThread().getPriority());
        throw new RuntimeException("Intentional Exception");
    }
});

γ……

이 μ½”λ“œμ—μ„œλŠ” 읡λͺ… 클래슀λ₯Ό μ‚¬μš©ν•˜μ—¬ Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜μ˜€μœΌλ©°, run() λ©”μ„œλ“œ λ‚΄μ—μ„œ μŠ€λ ˆλ“œ 이름과 μš°μ„ μˆœμœ„λ₯Ό 좜λ ₯ν•œ ν›„ μ˜λ„μ μœΌλ‘œ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” λ‘œμ§μ„ λ‹΄κ³  μžˆλ‹€.

 

3. μŠ€λ ˆλ“œμ˜ μ‹€ν–‰κ³Ό 관리

μŠ€λ ˆλ“œ μ‹œμž‘

μŠ€λ ˆλ“œλ₯Ό μƒμ„±ν•œ ν›„μ—λŠ” start() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄μ•Ό JVM이 μƒˆλ‘œμš΄ μŠ€λ ˆλ“œλ₯Ό μƒμ„±ν•˜κ³  μš΄μ˜μ²΄μ œμ— μ „λ‹¬ν•˜κ²Œ λœλ‹€. 즉, λ‹¨μˆœνžˆ μŠ€λ ˆλ“œ 객체λ₯Ό μƒμ„±ν•˜λŠ” κ²ƒλ§ŒμœΌλ‘œλŠ” μŠ€λ ˆλ“œκ°€ μ‹€ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€.

thread.start();

ν˜„μž¬ μ‹€ν–‰ 쀑인 μŠ€λ ˆλ“œ 확인

메인 μŠ€λ ˆλ“œμ™€ μƒˆλ‘œμš΄ μŠ€λ ˆλ“œμ˜ μ‹€ν–‰ μˆœμ„œλ₯Ό ν™•μΈν•˜κΈ° μœ„ν•΄, Thread.currentThread() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•΄ ν˜„μž¬ μ‹€ν–‰ 쀑인 μŠ€λ ˆλ“œ 정보λ₯Ό 얻을 수 μžˆλ‹€.

System.out.println("[μƒˆ μŠ€λ ˆλ“œ μ‹œμž‘ μ „] Thread.currentThread().getName() = " + Thread.currentThread().getName());

μŠ€λ ˆλ“œ μΌμ‹œμ •μ§€

Thread.sleep() λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜λ©΄ ν˜„μž¬ μŠ€λ ˆλ“œλ₯Ό 일정 μ‹œκ°„ λ™μ•ˆ μΌμ‹œμ •μ§€μ‹œν‚¬ 수 μžˆλ‹€. 이 경우, CPU μžμ›μ„ μ†Œλͺ¨ν•˜μ§€ μ•Šκ³  μš΄μ˜μ²΄μ œμ— μ˜ν•΄ ν•΄λ‹Ή μ‹œκ°„ λ™μ•ˆ μŠ€μΌ€μ€„λ˜μ§€ μ•ŠλŠ”λ‹€.

Thread.sleep(10000);

 

4. μŠ€λ ˆλ“œμ˜ 이름과 μš°μ„ μˆœμœ„ μ„€μ •

μŠ€λ ˆλ“œ 이름 λ³€κ²½

기본적으둜 μƒˆλ‘œ μƒμ„±λœ μŠ€λ ˆλ“œλŠ” “Thread-0”κ³Ό 같이 μžλ™μœΌλ‘œ 이름이 μ§€μ •λœλ‹€. κ·ΈλŸ¬λ‚˜ 의미 μžˆλŠ” 이름을 μ„€μ •ν•˜λŠ” 것이 디버깅과 관리에 도움이 λœλ‹€.
이λ₯Ό μœ„ν•΄ setName() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

thread.setName("New Worker μŠ€λ ˆλ“œ");

 

μŠ€λ ˆλ“œ μš°μ„ μˆœμœ„ μ„€μ •

Java μŠ€λ ˆλ“œλŠ” 1λΆ€ν„° 10κΉŒμ§€μ˜ μš°μ„ μˆœμœ„λ₯Ό μ§€μ •ν•  수 있으며, κΈ°λ³Έ μš°μ„ μˆœμœ„λŠ” Thread.NORM_PRIORITY이닀.
νŠΉμ • μŠ€λ ˆλ“œμ˜ 응닡성을 λ†’μ΄κ±°λ‚˜ μ€‘μš”λ„λ₯Ό λ°˜μ˜ν•˜κΈ° μœ„ν•΄ setPriority() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

thread.setPriority(Thread.MAX_PRIORITY); //μš΄μ„  μˆœμœ„ μ§€μ •(10=max) => 응닡성 높아짐

 

μ‹€ν–‰ 쀑 getPriority() λ©”μ„œλ“œλ₯Ό 톡해 μš°μ„ μˆœμœ„λ₯Ό 확인할 수 있으며, 이λ₯Ό 톡해 μ„€μ •ν•œ 값이 μ˜¬λ°”λ₯΄κ²Œ μ μš©λ˜μ—ˆλŠ”μ§€ 검증할 수 μžˆλ‹€.

5. μ˜ˆμ™Έ 처리 및 Uncaught Exception Handler

μŠ€λ ˆλ“œ λ‚΄μ—μ„œ λ°œμƒν•œ unchecked μ˜ˆμ™Έκ°€ 적절히 μ²˜λ¦¬λ˜μ§€ μ•ŠμœΌλ©΄ μŠ€λ ˆλ“œ 전체가 μ’…λ£Œλ  수 μžˆλŠ”λ°,
이λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ setUncaughtExceptionHandler() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ˜ˆμ™Έ 처리 ν•Έλ“€λŸ¬λ₯Ό 등둝할 수 μžˆλ‹€.
μ˜ˆμ™Έ 처리 ν•Έλ“€λŸ¬λŠ” ν•΄λ‹Ή μŠ€λ ˆλ“œμ—μ„œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ—¬ catch λΈ”λ‘μ—μ„œ μ²˜λ¦¬λ˜μ§€ μ•Šμ€ 경우 μžλ™μœΌλ‘œ ν˜ΈμΆœλœλ‹€.

thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("μŠ€λ ˆλ“œμ—μ„œ 치λͺ…적인 error λ°œμƒ  = " + t.getName() + " \nλ°œμƒ error = " + e.getMessage());
    }
});

 

6. 전체 μ½”λ“œ

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // μš΄μ˜μ²΄μ œμ— μ˜ν•΄ μŠ€μΌ€μ€„ 되면 ν•΄λ‹Ή μŠ€λ ˆλ“œμ—μ„œ 싀행될 둜직
                System.out.println("run() 호좜 : " + Thread.currentThread().getName());
                System.out.println("Thread.currentThread().getPriority() = " + Thread.currentThread().getPriority());
                throw new RuntimeException("Intentional Exception");
            }
        });

        thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("μŠ€λ ˆλ“œμ—μ„œ 치λͺ…적인 error λ°œμƒ  = " + t.getName() + " \nλ°œμƒ error = " + e.getMessage());
            }
        });

        thread.setName("New Worker μŠ€λ ˆλ“œ"); // κΈ°λ³Έ Thread-0 λŒ€μ‹  μƒˆ 이름 μ§€μ •
        thread.setPriority(Thread.MAX_PRIORITY); // μš°μ„ μˆœμœ„ μ§€μ • (10 = MAX)

        System.out.println("[μƒˆ μŠ€λ ˆλ“œ μ‹œμž‘ μ „] Thread.currentThread().getName() = " + Thread.currentThread().getName());
        thread.start(); // JVM이 μƒˆ μŠ€λ ˆλ“œλ₯Ό 생성해 OS에 전달
        System.out.println("[μƒˆ μŠ€λ ˆλ“œ μ‹œμž‘ ν›„] Thread.currentThread().getName() = " + Thread.currentThread().getName());

        // ν˜„μž¬ μ‹€ν–‰ 쀑인 μŠ€λ ˆλ“œλ₯Ό 일정 μ‹œκ°„ λ™μ•ˆ μ •μ§€μ‹œν‚΄ (CPU μ†Œλͺ¨ μ—†μŒ)
        Thread.sleep(10000);
    }
}

 

μΆ”κ°€ - 디버깅과 μŠ€λ ˆλ“œ 관리

IDEλ₯Ό ν™œμš©ν•˜λ©΄ λ©€ν‹°μŠ€λ ˆλ”© μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 디버깅이 μš©μ΄ν•΄μ§„λ‹€.
디버그 λͺ¨λ“œμ—μ„œ λΈŒλ ˆμ΄ν¬ν¬μΈνŠΈλ₯Ό μ„€μ •ν•˜κ³  μŠ€λ ˆλ“œ 탭을 ν™•μΈν•˜λ©΄ ν˜„μž¬ μ‹€ν–‰ 쀑인 λͺ¨λ“  μŠ€λ ˆλ“œμ™€ 각 μŠ€λ ˆλ“œμ˜ μŠ€νƒ 트레이슀λ₯Ό 확인할 수 μžˆλ‹€. λΈŒλ ˆμ΄ν¬ν¬μΈνŠΈμ— λ„λ‹¬ν•˜λ©΄ λͺ¨λ“  μŠ€λ ˆλ“œκ°€ μΌμ‹œμ •μ§€λ˜λ―€λ‘œ, 각 μŠ€λ ˆλ“œλ₯Ό κ°œλ³„μ μœΌλ‘œ 뢄석할 수 μžˆλ‹€.

 

 

 

 

 

참고 자료:

Udemy - Java λ©€ν‹°μŠ€λ ˆλ”©, 병행성 및 병렬 μ‹€ν–‰ ν”„λ‘œκ·Έλž˜λ° μ „λ¬Έκ°€ 되기

https://docs.oracle.com/javase/10/docs/api/java/lang/Thread.State.html

 

Thread.State (Java SE 10 & JDK 10 )

 

docs.oracle.com

 

728x90