Tistory λΈλ‘κ·Έ ν¬μ€ν λ°λ‘κ°κΈ°
Javaμ λμμ± μ리μ¦μ 첫 λ²μ§Έ μ£Όμ λ‘ Thread μμ± λ° μμ λ°©λ²κ³Ό sleep, interrupt, joinμ λν΄ μμλ³΄κ² μ΅λλ€.
Javaμμ threadλ₯Ό μμ±νλ λ°©λ²μ μ¬λ¬ κ°μ§κ° μμ΅λλ€.
Thread
ν΄λμ€λ₯Ό μμν μλΈν΄λμ€λ₯Ό μμ±ν΄μrun()
λ©μλλ₯Ό μ€λ²λΌμ΄λ νλ λ°©λ²- Anonymous
Thread
ν΄λμ€λ₯Ό μμ±ν΄μrun()
λ©μλλ₯Ό μ€λ²λΌμ΄λ νλ λ°©λ² (λ± ν λ²λ§ μ€ννκ³ μΆμ κ²½μ° μ’λ€.) 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();
}
}
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
ν΄λμ€λ₯Ό νμ©νλ λ°©λ²κ³Ό Runnable
μΈν°νμ΄μ€λ₯Ό νμ©νλ λ°©λ² μ€ λ¬΄μμ μ¬μ©ν΄μΌ νλ κ² μ’μκΉμ?
μ λ΅μ μμ§λ§ λ³΄ν΅ Runnable
μΈν°νμ΄μ€λ₯Ό ꡬννλ λ°©μμ΄ λ μ μ°νκ³ νΈνκΈ° λλ¬Έμ λ λ§μ΄ νμ©ν©λλ€.
Java APIμλ Runnable
μΈμ€ν΄μ€λ₯Ό λ겨μΌνλ λΆλΆμ΄ λ§κ³ , Lambda Expressionμ΄ μΆκ°λ νλ‘ Anonymous Runnable μΈμ€ν΄μ€λ₯Ό νμ©νλ κ² λ§μ΄ νΈν΄μ‘κΈ° λλ¬Έμ
λλ€.
κ·Έλ λ€λ©΄ μ¬μ©ν μ°λ λλ μΈμ μ’ λ£λ κΉμ?
μ¬μ©ν threadλ run()
λ©μλκ° μ€νμ λ§μ³€μ λ μ’
λ£λκ² λ©λλ€.
μ¬κΈ°μ μ κΉ, 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());
}
}
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();
}
}
νμ§λ§ μμ κ°μ΄ run()
λ©μλλ₯Ό νΈμΆνλ©΄ μλ‘ μμ±ν anotherThread
μμ run()
λ©μλκ° μ€νλλ κ²μ΄ μλ main
μ°λ λμμ μ€νλκ² λ©λλ€.
μ΄λ° μ΄μ λ‘ μ°λ λλ₯Ό μ¬μ©ν λλ run()
λ©μλλ₯Ό μ§μ νΈμΆνμ§ μκ³ start()
λ©μλλ₯Ό νΈμΆν΄μΌ ν©λλ€.
Threadλ₯Ό νμ©ν΄μ ν μ μλ μμ μ μ¬λ¬ κ°μ§κ° μμ΅λλ€.
sleep λ©μλλ₯Ό μ¬μ©ν΄μ threadμ μ€νμ μ€μ§ν μ μκ³ , νΉμ μΈν°λ²μ λκ³ μκ°λ§λ€ 무μΈκ°λ₯Ό μ€ννκ² ν μλ μμ΅λλ€.
μλ₯Ό λ€λ©΄, 15μ΄μ ν λ²μ© νμΌμ 무μΈκ°λ₯Ό μΈ μλ μκ³ , 2μ΄λ§λ€ μμ²ν λ°μ΄ν°λ₯Ό νμΈν μλ μμ΅λλ€.
κ·Έλ¦¬κ³ μ¬λ¬ κ°μ μ°λ λλ₯Ό λ€λ£° λ μ°λ λ κ° μλ‘ μμ‘΄μμΌ νμ©νλ©΄μ μμμ ν¨μ¨μ μΌλ‘ νμ©ν μ μκ²λ ν μλ μμ΅λλ€.
μλ₯Ό λ€λ©΄, λ€λ₯Έ μ°λ λκ° 10μ΄ λμ μ€νν κ²°κ³Όλ₯Ό νμ¬ μ°λ λκ° νμλ‘ ν λ, νμ¬ μ°λ λλ₯Ό κ³μ μ€νμν€λ κ²μ΄ μλλΌ, λ€λ₯Έ μ°λ λκ° μμ νλ 10μ΄ λμ νμ¬ μ°λ λλ₯Ό μ€μ§ν΄λκ³ λ€λ₯Έ μ°λ λμ κ²°κ³Όλ₯Ό κΈ°λ€λ¦¬κ² ν μ μμ΅λλ€.
μ μμ λ€ μΈμλ ν μ μλ κ²μ λ§κ² μ§λ§, μ΄λ° μμ λ€μ κ°λ₯νκ² ν΄μ£Όλ sleep, interrupt, join κ°λ μ λν΄ μμλ³΄κ² μ΅λλ€.
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();
}
}
μΈν°λ½νΈλ λ€λ₯Έ μμ μ νκΈ° μν΄ νλ μμ μ λ°©ν΄νλ λͺ λ Ήμ λλ€.
λ€λ₯Έ μ°λ λκ° κ°μ Έμ€λ λ°μ΄ν° λ²νΌλ₯Ό λͺ¨λν°λ§νλ μ°λ λκ° μ€νμ€μ΄λΌκ³ κ°μ ν΄λ΄ μλ€.
λ°μ΄ν°λ₯Ό κ°μ Έμ€λ μ°λ λκ° λ μ΄μ κ°μ Έμ¬ λ°μ΄ν°κ° μλ€λ©΄ λͺ¨λν°λ§ μ€μΈ μ°λ λλ μ€νμ λ©μΆ°λ λκ² μ£ ?
μ°λ λμ μΈν°λ½νΈκ° λ°μνλμ§ μ μ μλ λ°©λ²μ λ κ°μ§κ° μμ΅λλ€.
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();
}
}
μμ κ°μ΄ μ€ννλ©΄ 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();
}
}
Thread.sleep()
μ€ν μ€ interruptκ° λ°μν΄μ InterruptedException
μ΄ throw λμκ³ , ν΄λΉ μ°λ λλ return
λ¬Έμ λ§λ κ·Έ μ리μμ μ€νμ λ©μΆκ² λ κ²μ
λλ€.
λ°μ΄ν°λ₯Ό κ°μ Έμ€λ 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
κ° μ’
λ£λ λκΉμ§ κΈ°λ€λ Έλ€κ° μ΄μ΄μ μ€ννλ μμμ
λλ€.
AnotherThread
μμ "AnotherThread: 3μ΄ λ€ κΉ¨μ΄λ¨"
λ©μΈμ§λ₯Ό νλ¦°νΈνλ©° μ’
λ£λμ μ€νμ μ μ λ©μΆ myRunnableThread
κ° μ΄μ΄μ μ€νλμ΄ "myRunnableThread: AnotherThread μ’
λ£ νμΈ. μ΄μ΄μ μ€ν μμ."
κ° νλ¦°νΈλ κ²μ νμΈν μ μμ΅λλ€.
μ μμλ μμ£Ό κ°λ¨ν μμλΌμ λ³λ¬Έμ μμ΄ μλνμ§λ§, μ¬κΈ°μλ μκ°ν΄λ΄μΌ νλ λ¬Έμ κ° μμ΅λλ€.
λ§μ½ 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 κ°μ μΆκ°νμ΅λλ€.
μ€ν κ²°κ³Όλ₯Ό νμΈν΄λ³ΌκΉμ?
AnotherThread
κ° 5μ΄ λμ sleep
μ νλλ° MyRunnable
μ 2μ΄μ μ νμ λμκΈ°μ 2μ΄κ° κΈ°λ€λ¦° λ€ κΈ°λ€λ¦¬λ κ²μ λ©μΆκ³ μ΄μ΄μ μ€νλκ³ , AnotherThread
λ κ·Έλ‘λΆν° μ½ 3μ΄ λ€ μ΄μ΄μ μ€νλ λ€ μ’
λ£λλ κ²μ νμΈν μ μμ΅λλ€.
μ΄λ κ² Thread μμ± λ° μμ λ°©λ²κ³Ό sleep, interrupt, joinμ λν΄ μμ보μμ΅λλ€.
Javaλ multi-threaded μΈμ΄μ΄κΈ° λλ¬Έμ threadμ λν μ΄ν΄κ° μ€μν©λλ€.
Javaμ λμμ± μλ¦¬μ¦ λ€μ νΈμλ μ¬λ¬ κ°μ μ°λ λλ₯Ό λ€λ£¨λ©΄μ μκΈΈ μ μλ λ¬Έμ μ λ€κ³Ό ν΄κ²°λ°©λ² λ±μ λν΄ λ€λ£° μμ μ λλ€.