Skip to content

Latest commit

Β 

History

History

concurrency-in-java-threads-intro

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Β 
Β 
Β 
Β 

[Java의 λ™μ‹œμ„± #1] Threads (생성, μ‚¬μš©, sleep, interrupt, join)

Tistory λΈ”λ‘œκ·Έ ν¬μŠ€νŒ… λ°”λ‘œκ°€κΈ°

Java의 λ™μ‹œμ„± μ‹œλ¦¬μ¦ˆμ˜ 첫 번째 주제둜 Thread 생성 및 μ‹œμž‘ 방법과 sleep, interrupt, join에 λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

Thread 생성 방법과 μ‚¬μš©

Javaμ—μ„œ threadλ₯Ό μƒμ„±ν•˜λŠ” 방법은 μ—¬λŸ¬ 가지가 μžˆμŠ΅λ‹ˆλ‹€.

  1. Thread 클래슀λ₯Ό μƒμ†ν•œ μ„œλΈŒν΄λž˜μŠ€λ₯Ό μƒμ„±ν•΄μ„œ run() λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œ ν•˜λŠ” 방법
  2. Anonymous Thread 클래슀λ₯Ό μƒμ„±ν•΄μ„œ run() λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œ ν•˜λŠ” 방법 (λ”± ν•œ 번만 μ‹€ν–‰ν•˜κ³  싢은 경우 μ’‹λ‹€.)
  3. Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 방법

1. Thread 클래슀λ₯Ό μƒμ†ν•œ μ„œλΈŒν΄λž˜μŠ€λ₯Ό μƒμ„±ν•΄μ„œ run() λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œ ν•˜λŠ” 방법

// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread anotherThread = new AnotherThread();
        anotherThread.start();
    }
}
// AnotherThread.java

public class AnotherThread extends Thread {
    @Override
    public void run() {
        System.out.println("From another thread");
    }
}

μ—¬κΈ°μ„œ 같은 AnotherThread μΈμŠ€ν„΄μŠ€λ₯Ό μž¬μ‚¬μš©ν•΄μ„œ start()λ₯Ό μ—¬λŸ¬λ²ˆ ν˜ΈμΆœν•˜λŠ” 것은 λΆˆκ°€λŠ₯ν•©λ‹ˆλ‹€.

// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread anotherThread = new AnotherThread();
        anotherThread.start();
        anotherThread.start();
    }
}

μ΄λ ‡κ²Œ μ‹€ν–‰μ‹œ IllegalThreadStateException이 λ°œμƒν•©λ‹ˆλ‹€.

2. Anonymous Thread 클래슀λ₯Ό μƒμ„±ν•΄μ„œ run() λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œ ν•˜λŠ” 방법 (λ”± ν•œ 번만 μ‹€ν–‰ν•˜κ³  싢은 경우 μ’‹λ‹€.)

// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        new Thread() {
            public void run() {
                System.out.println("From the anonymous class thread");
            }
        }.start();
    }
}

3. Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 방법

Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•  경우 κΌ­ Thread ν΄λž˜μŠ€κ°€ μ•„λ‹ˆλ”λΌλ„ μ–΄λ–€ 클래슀던 ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ λ‹€μŒ run() λ©”μ†Œλ“œλ§Œ μ˜€λ²„λΌμ΄λ“œ ν•΄μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

그리고 ν•΄λ‹Ή threadμ—μ„œ μ‹€ν–‰ν•˜κ³  싢은 μ½”λ“œλ₯Ό run() λ©”μ†Œλ“œμ— μž‘μ„±ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€.

// MyRunnable.java

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("From MyRunnable");
    }
}

μœ„μ™€ 같이 Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀λ₯Ό μƒμ„±ν•˜κ³  run() λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ“œ ν•΄μ€λ‹ˆλ‹€.

MyRunnable을 μƒˆλ‘œμš΄ threadμ—μ„œ μ‹€ν–‰ν•˜λ €λ©΄ Thread ν΄λž˜μŠ€μ— MyRunnable μΈμŠ€ν„΄μŠ€λ₯Ό λ„˜κ²¨μ£Όλ©΄ λ©λ‹ˆλ‹€.

// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread myRunnableThread = new Thread(new MyRunnable());
        myRunnableThread.start();
    }
}

Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” κ²½μš°λ„ Anonymous Thread 클래슀λ₯Ό μƒμ„±ν•˜λŠ” 방법을 ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread myRunnableThread = new Thread(new MyRunnable() {
            @Override
            public void run() {
                System.out.println("From the anonymous implementation of run()");
            }
        });

        myRunnableThread.start();
    }
}

Thread 클래슀 vs Runnable μΈν„°νŽ˜μ΄μŠ€

Thread 클래슀λ₯Ό ν™œμš©ν•˜λŠ” 방법과 Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν™œμš©ν•˜λŠ” 방법 쀑 무엇을 μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” 게 μ’‹μ„κΉŒμš”?

정닡은 μ—†μ§€λ§Œ 보톡 Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 방식이 더 μœ μ—°ν•˜κ³  νŽΈν•˜κΈ° λ•Œλ¬Έμ— 더 많이 ν™œμš©ν•©λ‹ˆλ‹€.

Java API에도 Runnable μΈμŠ€ν„΄μŠ€λ₯Ό λ„˜κ²¨μ•Όν•˜λŠ” 뢀뢄이 많고, Lambda Expression이 μΆ”κ°€λœ ν›„λ‘œ Anonymous Runnable μΈμŠ€ν„΄μŠ€λ₯Ό ν™œμš©ν•˜λŠ” 게 많이 νŽΈν•΄μ‘ŒκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

μƒμ„±ν•œ thread μ’…λ£Œ μ‹œμ ?

κ·Έλ ‡λ‹€λ©΄ μ‚¬μš©ν•œ μ“°λ ˆλ“œλŠ” μ–Έμ œ μ’…λ£Œλ κΉŒμš”?

μ‚¬μš©ν•œ threadλŠ” run() λ©”μ†Œλ“œκ°€ 싀행을 λ§ˆμ³€μ„ λ•Œ μ’…λ£Œλ˜κ²Œ λ©λ‹ˆλ‹€.

Thread μ‚¬μš© μ‹œ μ£Όμ˜μ‚¬ν•­ (run() vs start())

μ—¬κΈ°μ„œ 잠깐, Threadλ₯Ό μ‚¬μš©ν•  λ•Œ μ£Όμ˜μ‚¬ν•­μ΄ ν•˜λ‚˜ μžˆμŠ΅λ‹ˆλ‹€.

Thread 클래슀의 run() λ©”μ†Œλ“œλ₯Ό 직접 ν˜ΈμΆœν•˜λŠ” 게 μ•„λ‹Œ start() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€λŠ” μ μž…λ‹ˆλ‹€.

run() λ©”μ†Œλ“œλŠ” JVM이 λ‚΄λΆ€μ μœΌλ‘œ ν˜ΈμΆœν•˜λŠ” λ©”μ†Œλ“œμ΄λ©°, run() λ©”μ†Œλ“œλ₯Ό 직접 ν˜ΈμΆœν•  μ‹œ μƒˆλ‘œ μƒμ„±ν•œ threadμ—μ„œ μ‹€ν–‰ν•˜λŠ” 게 μ•„λ‹Œ run() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” threadμ—μ„œ μ‹€ν–‰ν•˜κ²Œ 되기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread anotherThread = new AnotherThread();
        anotherThread.setName("*** Another Thread ***")
        anotherThread.start();
    }
}
// AnotherThread.java

public class AnotherThread extends Thread {
    @Override
    public void run() {
        System.out.println("From " + currentThread().getName());
    }
}

1

start()λ₯Ό ν˜ΈμΆœν•˜λ©΄ μœ„μ™€ 같이 μ •μƒμ μœΌλ‘œ μƒˆλ‘œ μƒμ„±ν•œ μ“°λ ˆλ“œμ—μ„œ run() λ©”μ†Œλ“œκ°€ μ‹€ν–‰λ˜λŠ” 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread anotherThread = new AnotherThread();
        anotherThread.setName("*** Another Thread ***")
        // anotherThread.start();
        anotherThread.run();
    }
}

2

ν•˜μ§€λ§Œ μœ„μ™€ 같이 run() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λ©΄ μƒˆλ‘œ μƒμ„±ν•œ anotherThreadμ—μ„œ run() λ©”μ†Œλ“œκ°€ μ‹€ν–‰λ˜λŠ” 것이 μ•„λ‹Œ main μ“°λ ˆλ“œμ—μ„œ μ‹€ν–‰λ˜κ²Œ λ©λ‹ˆλ‹€.

이런 이유둜 μ“°λ ˆλ“œλ₯Ό μ‚¬μš©ν•  λ•ŒλŠ” run() λ©”μ†Œλ“œλ₯Ό 직접 ν˜ΈμΆœν•˜μ§€ μ•Šκ³  start() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•©λ‹ˆλ‹€.


Sleep, Interrupts, Join

Threadλ₯Ό ν™œμš©ν•΄μ„œ ν•  수 μžˆλŠ” μž‘μ—…μ€ μ—¬λŸ¬ 가지가 μžˆμŠ΅λ‹ˆλ‹€.

sleep λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄μ„œ thread의 싀행을 쀑지할 수 있고, νŠΉμ • μΈν„°λ²Œμ„ 두고 μ‹œκ°„λ§ˆλ‹€ 무언가λ₯Ό μ‹€ν–‰ν•˜κ²Œ ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€λ©΄, 15μ΄ˆμ— ν•œ λ²ˆμ”© νŒŒμΌμ— 무언가λ₯Ό μ“Έ μˆ˜λ„ 있고, 2μ΄ˆλ§ˆλ‹€ μš”μ²­ν•œ 데이터λ₯Ό 확인할 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

그리고 μ—¬λŸ¬ 개의 μ“°λ ˆλ“œλ₯Ό λ‹€λ£° λ•Œ μ“°λ ˆλ“œ κ°„ μ„œλ‘œ μ˜μ‘΄μ‹œμΌœ ν™œμš©ν•˜λ©΄μ„œ μžμ›μ„ 효율적으둜 ν™œμš©ν•  수 μžˆκ²Œλ” ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€λ©΄, λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ 10초 λ™μ•ˆ μ‹€ν–‰ν•œ κ²°κ³Όλ₯Ό ν˜„μž¬ μ“°λ ˆλ“œκ°€ ν•„μš”λ‘œ ν•  λ•Œ, ν˜„μž¬ μ“°λ ˆλ“œλ₯Ό 계속 μ‹€ν–‰μ‹œν‚€λŠ” 것이 μ•„λ‹ˆλΌ, λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ μž‘μ—…ν•˜λŠ” 10초 λ™μ•ˆ ν˜„μž¬ μ“°λ ˆλ“œλ₯Ό 쀑지해놓고 λ‹€λ₯Έ μ“°λ ˆλ“œμ˜ κ²°κ³Όλ₯Ό κΈ°λ‹€λ¦¬κ²Œ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μœ„ μž‘μ—…λ“€ 외에도 ν•  수 μžˆλŠ” 것은 λ§Žκ² μ§€λ§Œ, 이런 μž‘μ—…λ“€μ„ κ°€λŠ₯ν•˜κ²Œ ν•΄μ£ΌλŠ” sleep, interrupt, join κ°œλ…μ— λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

Sleep

Thread.sleep() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄μ„œ μ“°λ ˆλ“œλ₯Ό 3초 λ™μ•ˆ λ©ˆμ·„λ‹€ μ‹€ν–‰μ‹œν‚€λŠ” μ˜ˆμ‹œλ₯Ό ν™•μΈν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

// AnotherThread.java

public class AnotherThread extends Thread {
    @Override
    public void run() {
        System.out.println("From " + currentThread().getName());

        try {
            Thread.sleep(3000);
        } catch (InterruptedException ie) {
            System.out.println("AnotherThread: Interrupt λ°œμƒ");
            return;
        }

        System.out.println("AnotherThread: 3초 λ’€ 깨어남");
    }
}
// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread anotherThread = new AnotherThread();
        anotherThread.setName("*** Another Thread ***");
        anotherThread.start();
    }
}

3

Interrupts

μΈν„°λŸ½νŠΈλž€ λ‹€λ₯Έ μž‘μ—…μ„ ν•˜κΈ° μœ„ν•΄ ν•˜λ˜ μž‘μ—…μ„ λ°©ν•΄ν•˜λŠ” λͺ…λ Ήμž…λ‹ˆλ‹€.

λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ κ°€μ Έμ˜€λŠ” 데이터 버퍼λ₯Ό λͺ¨λ‹ˆν„°λ§ν•˜λŠ” μ“°λ ˆλ“œκ°€ 싀행쀑이라고 κ°€μ •ν•΄λ΄…μ‹œλ‹€.

데이터λ₯Ό κ°€μ Έμ˜€λŠ” μ“°λ ˆλ“œκ°€ 더 이상 κ°€μ Έμ˜¬ 데이터가 μ—†λ‹€λ©΄ λͺ¨λ‹ˆν„°λ§ 쀑인 μ“°λ ˆλ“œλŠ” 싀행을 λ©ˆμΆ°λ„ 되겠죠?

μ“°λ ˆλ“œμ— μΈν„°λŸ½νŠΈκ°€ λ°œμƒν–ˆλŠ”μ§€ μ•Œ 수 μžˆλŠ” 방법은 두 가지가 μžˆμŠ΅λ‹ˆλ‹€.

InterruptedException을 catch ν•˜λŠ” 방법이 있고,

λ§Œμ•½ run() λ©”μ†Œλ“œκ°€ InterruptedException을 λ°œμƒμ‹œν‚€λŠ” λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•˜μ§€ μ•ŠλŠ” 경우, interrupt() λ©”μ†Œλ“œλ₯Ό 주기적으둜 μ‹€ν–‰ν•΄μ„œ μΈν„°λŸ½νŠΈκ°€ λ°œμƒν–ˆλŠ”μ§€ ν™•μΈν•˜λŠ” 방법이 μžˆμŠ΅λ‹ˆλ‹€.

μ“°λ ˆλ“œ κ°„ μ„œλ‘œ μ–΄λ–»κ²Œ μΈν„°λŸ½νŠΈλ₯Ό λ°œμƒμ‹œν‚¬κΉŒμš”?

λ©ˆμΆ”κ³ μž ν•˜λŠ” μ“°λ ˆλ“œ μΈμŠ€ν„΄μŠ€μ˜ interrupt() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.

λ¬Όλ‘  이럴 경우 λ©ˆμΆ”κ³ μž ν•˜λŠ” μ“°λ ˆλ“œ μΈμŠ€ν„΄μŠ€μ— λŒ€ν•œ λ ˆνΌλŸ°μŠ€κ°€ μ‘΄μž¬ν•΄μ•Ό ν•©λ‹ˆλ‹€.

// AnotherThread.java

public class AnotherThread extends Thread {
    @Override
    public void run() {
        System.out.println("From " + currentThread().getName());

        try {
            Thread.sleep(3000);
        } catch (InterruptedException ie) {
            System.out.println("AnotherThread: Interrupt λ°œμƒ");
            return;
        }

        System.out.println("AnotherThread: 3초 λ’€ 깨어남");
    }
}
// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread anotherThread = new AnotherThread();
        anotherThread.setName("*** Another Thread ***");
        anotherThread.start();
    }
}

3

μœ„μ™€ 같이 μ‹€ν–‰ν•˜λ©΄ AnotherThread의 Thread.sleep(3000)이 방해받지 μ•Šκ³  μ‹€ν–‰λ˜μ–΄ 3초 뒀에 "AnotherThread: 3초 λ’€ 깨어남"λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

μ—¬κΈ°μ„œ anotherThread에 interrupt() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•΄μ„œ μΈν„°λŸ½νŠΈλ₯Ό λ°œμƒμ‹œμΌœλ³΄κ² μŠ΅λ‹ˆλ‹€.

// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread anotherThread = new AnotherThread();
        anotherThread.setName("*** Another Thread ***");
        anotherThread.start();

        Thread myRunnableThread = new Thread(new MyRunnable() {
            @Override
            public void run() {
                System.out.println("From the anonymous implementation of run()");
            }
        });
        myRunnableThread.start();
        anotherThread.interrupt();
    }
}

4

Thread.sleep() μ‹€ν–‰ 쀑 interruptκ°€ λ°œμƒν•΄μ„œ InterruptedException이 throw λ˜μ—ˆκ³ , ν•΄λ‹Ή μ“°λ ˆλ“œλŠ” return문을 λ§Œλ‚˜ κ·Έ μžλ¦¬μ—μ„œ 싀행을 λ©ˆμΆ”κ²Œ 된 κ²ƒμž…λ‹ˆλ‹€.

Join

데이터λ₯Ό κ°€μ Έμ˜€λŠ” thread Bκ°€ 있고 μ’…ν•©λœ 데이터λ₯Ό μ²˜λ¦¬ν•˜λŠ” thread Aκ°€ μžˆλ‹€κ³  κ°€μ •ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

thread AλŠ” thread Bκ°€ 데이터λ₯Ό μ „λΆ€ κ°€μ Έμ™€μ„œ μ’…λ£Œλ  λ•ŒκΉŒμ§€ μ΄μ–΄μ„œ 싀행될 수 μ—†λŠ” 상황이겠죠?

이런 경우, threadλ₯Ό 주기적으둜 κΉ¨μ›Œ μ‹€ν–‰ μ—¬λΆ€λ₯Ό νŒλ‹¨ν•˜λŠ” 것보닀, thread B의 μ’…λ£Œλ₯Ό κΈ°λ‹€λ¦¬λŠ” thread Aλ₯Ό thread B에 join ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

thread Aλ₯Ό thread B에 join ν•˜λ©΄, thread AλŠ” thread Bκ°€ μ’…λ£Œλ  λ•ŒκΉŒμ§€ κΈ°λ‹€λ Έλ‹€κ°€ μ’…λ£Œ μ‹œ μ΄μ–΄μ„œ μ‹€ν–‰λ©λ‹ˆλ‹€.

μ˜ˆμ‹œλ₯Ό 톡해 ν™•μΈν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

// AnotherThread.java

public class AnotherThread extends Thread {
    @Override
    public void run() {
        System.out.println("From " + currentThread().getName());

        try {
            Thread.sleep(3000);
        } catch (InterruptedException ie) {
            System.out.println("AnotherThread: Interrupt λ°œμƒ");
            return;
        }

        System.out.println("AnotherThread: 3초 λ’€ 깨어남");
    }
}
// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread anotherThread = new AnotherThread();
        anotherThread.setName("*** Another Thread ***");
        anotherThread.start();

        Thread myRunnableThread = new Thread(new MyRunnable() {
            @Override
            public void run() {
                System.out.println("From the anonymous implementation of run()");
                try {
                    anotherThread.join();
                    System.out.println("myRunnableThread: AnotherThread μ’…λ£Œ 확인. μ΄μ–΄μ„œ μ‹€ν–‰ μ‹œμž‘.");
                } catch (InterruptedException ie) {
                    System.out.println("myRunnableThread: μΈν„°λŸ½νŠΈ λ°œμƒ");
                }
            }
        });
        myRunnableThread.start();
    }
}

3초 λ™μ•ˆ sleep ν•˜λŠ” anotherThread에 myRunnableThreadλ₯Ό join ν•΄μ„œ anotherThreadκ°€ μ’…λ£Œλ  λ•ŒκΉŒμ§€ κΈ°λ‹€λ Έλ‹€κ°€ μ΄μ–΄μ„œ μ‹€ν–‰ν•˜λŠ” μ˜ˆμ‹œμž…λ‹ˆλ‹€.

5

AnotherThreadμ—μ„œ "AnotherThread: 3초 λ’€ 깨어남" 메세지λ₯Ό ν”„λ¦°νŠΈν•˜λ©° μ’…λ£Œλ˜μž 싀행을 μž μ‹œ 멈좘 myRunnableThreadκ°€ μ΄μ–΄μ„œ μ‹€ν–‰λ˜μ–΄ "myRunnableThread: AnotherThread μ’…λ£Œ 확인. μ΄μ–΄μ„œ μ‹€ν–‰ μ‹œμž‘."κ°€ ν”„λ¦°νŠΈλœ 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

timeout

μœ„ μ˜ˆμ‹œλŠ” μ•„μ£Ό κ°„λ‹¨ν•œ μ˜ˆμ‹œλΌμ„œ λ³„λ¬Έμ œ 없이 μž‘λ™ν•˜μ§€λ§Œ, μ—¬κΈ°μ—λŠ” 생각해봐야 ν•˜λŠ” λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.

λ§Œμ•½ join ν•œ λŒ€μƒμΈ AnotherThreadκ°€ μ ˆλŒ€ λλ‚˜μ§€ μ•ŠλŠ” κ²½μš°λŠ” μ–΄λ–»κ²Œ λ κΉŒμš”?

myRunnableThreadλŠ” AnotherThreadκ°€ μ’…λ£Œλ˜μ–΄μ•Ό μ΄μ–΄μ„œ μ‹€ν–‰λ˜κ³  μ΅œμ’…μ μœΌλ‘œ μ’…λ£Œλ  수 μžˆλŠ”λ°, AnotherThreadκ°€ 싀행을 λ©ˆμΆ”μ§€ μ•Šκ³  μ­‰ κ°„λ‹€λ©΄ μ•ˆλ˜κ² μ£ ?

이런 경우λ₯Ό λŒ€λΉ„ν•΄μ„œ join() λ©”μ†Œλ“œμ— timeout 값을 λ„˜κ²¨μ€„ 수 μžˆμŠ΅λ‹ˆλ‹€.

// AnotherThread.java

public class AnotherThread extends Thread {
    @Override
    public void run() {
        System.out.println("From " + currentThread().getName());

        try {
            Thread.sleep(5000);
        } catch (InterruptedException ie) {
            System.out.println("AnotherThread: Interrupt λ°œμƒ");
            return;
        }

        System.out.println("AnotherThread: 3초 λ’€ 깨어남");
    }
}
// Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println("From main thread");

        Thread anotherThread = new AnotherThread();
        anotherThread.setName("*** Another Thread ***");
        anotherThread.start();

        Thread myRunnableThread = new Thread(new MyRunnable() {
            @Override
            public void run() {
                System.out.println("From the anonymous implementation of run()");
                try {
                    anotherThread.join(2000);
                    System.out.println("myRunnableThread: AnotherThread μ’…λ£Œ ν˜Ήμ€ μ‹œκ΄€μ΄ˆκ³Ό (timed out). μ΄μ–΄μ„œ μ‹€ν–‰ μ‹œμž‘.");
                } catch (InterruptedException ie) {
                    System.out.println("myRunnableThread: μΈν„°λŸ½νŠΈ λ°œμƒ");
                }
            }
        });
        myRunnableThread.start();
    }
}

AnotherThread의 sleep μ‹œκ°„μ„ 5000ms둜 λ³€κ²½ν•˜κ³  MyRunnable의 join λ©”μ†Œλ“œμ— 2000ms의 timeout 값을 μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.

μ‹€ν–‰ κ²°κ³Όλ₯Ό ν™•μΈν•΄λ³ΌκΉŒμš”?

6

AnotherThreadκ°€ 5초 λ™μ•ˆ sleep을 ν•˜λŠ”λ° MyRunnable은 2초의 μ œν•œμ„ λ‘μ—ˆκΈ°μ— 2μ΄ˆκ°„ κΈ°λ‹€λ¦° λ’€ κΈ°λ‹€λ¦¬λŠ” 것을 λ©ˆμΆ”κ³  μ΄μ–΄μ„œ μ‹€ν–‰λ˜κ³ , AnotherThreadλŠ” κ·Έλ‘œλΆ€ν„° μ•½ 3초 λ’€ μ΄μ–΄μ„œ μ‹€ν–‰λœ λ’€ μ’…λ£Œλ˜λŠ” 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.


μ΄λ ‡κ²Œ Thread 생성 및 μ‹œμž‘ 방법과 sleep, interrupt, join에 λŒ€ν•΄ μ•Œμ•„λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

JavaλŠ” multi-threaded 언어이기 λ•Œλ¬Έμ— thread에 λŒ€ν•œ 이해가 μ€‘μš”ν•©λ‹ˆλ‹€.

Java의 λ™μ‹œμ„± μ‹œλ¦¬μ¦ˆ λ‹€μŒ νŽΈμ—λŠ” μ—¬λŸ¬ 개의 μ“°λ ˆλ“œλ₯Ό λ‹€λ£¨λ©΄μ„œ 생길 수 μžˆλŠ” λ¬Έμ œμ λ“€κ³Ό 해결방법 등에 λŒ€ν•΄ λ‹€λ£° μ˜ˆμ •μž…λ‹ˆλ‹€.