λͺ©ν
μλ°μ λ©ν°μ°λ λ νλ‘κ·Έλλ°μ λν΄ νμ΅νμΈμ.
νμ΅ν κ² (νμ)
- Thread ν΄λμ€μ Runnable μΈν°νμ΄μ€
- μ°λ λμ μν
- μ°λ λμ μ°μ μμ
- Main μ°λ λ
- λκΈ°ν
- λ°λλ½
λ§κ°μΌμ
2021λ 1μ 23μΌ ν μμΌ μ€ν 1μκΉμ§.
Thread ν΄λμ€μ Runnable μΈν°νμ΄μ€
Thread λ?
λμ νλ‘κ·Έλλ°μλ νλ‘μΈμ€μ μ€λ λμ λ κ°μ§ κΈ°λ³Έ μ€ν λ¨μκ° μμ΅λλ€. JAVA νλ‘κ·Έλλ° μΈμ΄μμ λμ νλ‘κ·Έλλ°μ λλΆλΆ μ€λ λμ κ΄λ ¨λ©λλ€.
νλ‘μΈμ€
νλ‘μΈμ€μλ μμ ν κ°μΈμ© κΈ°λ³Έ λ°νμ 리μμ€ μ§ν©μ΄ μκ³ μ체 λ©λͺ¨λ¦¬ 곡κ°λ μμ΅λλ€. JAVA κ°μ λ¨Έμ μ λλΆλΆμ ꡬνμ λ¨μΌ νλ‘μΈμ€λ‘ μ€νλ©λλ€.
μ€λ λ
μ€λ λλ κ²½λ νλ‘μΈμ€λΌκ³ λΆλ₯΄κΈ°λ ν©λλ€. νλ‘μΈμ€μ μ€λ λ λͺ¨λ μ€ν νκ²½μ μ 곡νμ§λ§ μ€λ λκ° νλ‘μΈμ€λ³΄λ€ λ§λλλ° νμν 리μμ€κ° λ μ μ΅λλ€.
μ€λ λλ νλ‘μΈμ€ λ΄μ μ‘΄μ¬νκ³ , λͺ¨λ νλ‘μΈμ€μλ μ΅μν νλμ μ€λ λκ° μ‘΄μ¬ν©λλ€. μ°λ¦¬κ° μλ° μ ν리μΌμ΄μ
μμ main()μ μ€ννλ©΄ λ©μΈ μ€λ λλΌκ³ νλ νλμ μ€λ λλ‘ μμμ νλ κ²μ
λλ€.
Threadλ₯Ό μννλ λ κ°μ§ λ°©λ²μ΄ μμ΅λλ€.
1. Thread ν΄λμ€ μμ
Thread ν΄λμ€μλ start() λ©μλκ° μμ΄μ νΈμΆνλ©΄ run() λ©μλκ° μ€νλκ² λλ€.
// μ€νκ²°κ³Ό
thread run.
μ€ν μμ
μ¬λ¬ κ°μ μ°λ λλ₯Ό μμ±ν΄μ μ€νν΄λ³΄λ©΄ μ΄λ¨κΉ?
μλ μ€ν κ²°κ³Όλ₯Ό 보면, μ€λ λμ μ€ν μμλ λλ€μ΄κ³ λ§€λ² λ°λκ² λλ€.
μ κΈ°ν 건 λͺ¨λ μ€λ λκ° μ’ λ£λκΈ°λ μ μ main λ©μλκ° μ’ λ£λμλ€.
1 thread start.
3 thread start.
2 thread start.
0 thread start.
4 thread start.
5 thread start.
6 thread start.
7 thread start.
8 thread start.
main end.
9 thread start.
1 thread end.
5 thread end.
9 thread end.
8 thread end.
3 thread end.
6 thread end.
2 thread end.
0 thread end.
7 thread end.
4 thread end.
2. Runnable μΈν°νμ΄μ€ ꡬν
- Runnable μΈν°νμ΄μ€μλ run() λ©μλλ§ κ΅¬νλμ΄ μλ€.
Threadν΄λμ€μ Runnableμ ꡬνν ν΄λμ€λ₯Ό λ겨μΌνλ€.
// μ€νκ²°κ³Ό
Hello from a thread!
Thread, Runnable λ μ€ μ΄λ€ κ²μ μ¬μ©ν΄μΌ ν κΉ?
- run() λ©μλ μ΄μΈμ λ€λ₯Έ λ©μλλ₯Ό μ€λ²λΌμ΄λ© ν΄μΌλ§ νλ€λ©΄ Thread ν΄λμ€
- run() λ©μλλ§ μ€λ²λΌμ΄λ© νλ€λ©΄, Runnable μΈν°νμ΄μ€λ₯Ό ꡬννλκ² μΌλ°μ μ΄λ€.
Threadμ μν
1. new (μμ±)
μ°λ λκ° μμ±λκ³ μμ§ start()κ° νΈμΆλμ§ μμ μνμ΄λ€.
2. Runnable (μ€λΉμν)
μ°λ λκ° μ€νλκΈ° μν μ€λΉλ¨κ³μ λλ€. CPUλ₯Ό μ μ νκ³ μμ§μμΌλ©° μ€ν(Running μν)μ νκΈ° μν΄ λκΈ°νκ³ μλ μνμ λλ€. μ½λ© μμμ start( ) λ©μλλ₯Ό νΈμΆνλ©΄ run( ) λ©μλμ μ€μ λ μ°λ λκ° Runnable μνλ‘ μ§μ ν©λλ€.
3. Running (μ€νμν)
CPUλ₯Ό μ μ νμ¬ μ€ννκ³ μλ μνμ΄λ©° run() λ©μλλ JVMλ§μ΄ νΈμΆ κ°λ₯. Runnable(μ€λΉμν)μ μλ μ¬λ¬ μ°λ λ μ€ μ°μ μμλ₯Ό κ°μ§ μ°λ λκ° κ²°μ λλ©΄ JVMμ΄ μλμΌλ‘ run( ) λ©μλλ₯Ό νΈμΆνμ¬ μ°λ λκ° Running μνλ‘ μ§μ .
4. Terminated (μ’ λ£μν)
μ°λ λκ° μ’ λ£λ μνμ΄λ€.
4. Blocked (μ§μ° μν)
CPUλ₯Ό μ μ κΆμ μμ€ν μνμ΄λ€. νμ νΉμ λ©μλλ₯Ό μ€νμμΌ Runnable(μ€λΉμν)λ‘ μ ν.
wait( ) λ©μλμ μν΄ Blocked μνκ° λ μ€λ λλ notify( ) λ©μλκ° νΈμΆλλ©΄ Runnable μνλ‘ κ°λ€. sleep(μκ°) λ©μλμ μν΄ Blocked μνκ° λ μ€λ λλ μ§μ λ μκ°μ΄ μ§λλ©΄ Runnable μνλ‘ κ°λ€.
Thread.sleep()
Thread.sleep(long millis) | (1 / 1000) μ΄ λ§νΌ Threadκ° μΌμμ μ§νλ€. |
Thread.sleep(long millis, int nanos) | (1 / 1000) μ΄ + (1 / 1,000,000,000) λλ Έμ΄ λ§νΌ μΌμμ μ§νλ€. |
InterruptedExceptionμ sleepμ΄ νμ± μν μΈ λμ λ€λ₯Έ μ€λ λκ° νμ¬ μ€λ λλ₯Ό μΈν°λ½νΈ ν λ sleepμ΄ λμ§λ μμΈμ΄λ€.
sleepμ μ¬μ©ν λμλ νμ try - catchλ‘ κ°μΈμ€μΌ νλ€.
κ·Έ μΈμ λ©μλ
Thread λ©μλ | μ€λͺ |
join() | ν΄λΉ μ°λ λκ° μ’ λ£λ λκΉμ§ κΈ°λ€λ¦°λ€. |
interrupt() | νμ¬ μ€ν μ€μΈ μ°λ λλ₯Ό μ€μ§μν¨λ€. (InterruptedException μμΈ λ°μ) |
yield() | μμ μ μμ μκ°μ λ€λ₯Έ μ°λ λμκ² μ보νκ³ μμ μ λκΈ°μνκ° λλ€. |
deprecated | |
deprecated | |
deprecated |
Threadμ μ°μ μμ
κ° Threadλ§λ€ μμ μ μ°μ μμλ₯Ό κ°μ§κ³ μλ€. μ΄ μ°μ μμκ° λμμλ‘ λ λ§μ μκ°λμ μμ μ μνν μ μλ€.
νμ§λ§ μ°μ μμκ° λλ€κ³ ν΄μ κ°μ₯ 빨리 μνλλκ²λ, κ°μ₯ λ¨Όμ μ€νλλ κ²λ μλλ€.
static int MAX_PRIORITY | μ°λ λμ MAX μ°μ μμ |
static int MIN_PRIORITY | μ°λ λμ MIN μ°μ μμ |
static int NORM_PRIORITY | μ°λ λκ° μμ±λ λ μ£Όμ΄μ§λ κΈ°λ³Έ μ°μ μμ (5) |
* (μ°λ λκ° κ°μ§ μ μλ μ°μ μμλ 1λΆν° 10κΉμ§μ΄λ€) |
setPriority() μ getPriority() λ©μλλ₯Ό μ΄μ©ν΄ μ°μ μμλ₯Ό λ°ννκ±°λ μ€μ ν μ μλ€.
Main Thread
Single Thread Application
javaμ main() λ©μλ " public static void main(String[] args) " μ΄κ²μ΄ λ©μΈ μ°λ λμ΄κ³ , λ€λ₯Έ μ°λ λλ₯Ό μμ±νλ©΄ λ©μΈ μ°λ λμμ νμλμ΄μ λ€λ₯Έ μ°λ λκ° μμ±λλ κ²μ΄λ€.
λ©μΈ μ°λ λ νλλ§ μ€νλλ κ²μ Single Thread Application μ΄λΌκ³ νλ€.
Multi Thread Application
λ©μΈ μ°λ λμμ λ€λ₯Έ μ°λ λλ₯Ό μμ±νμ¬ μ€ννλ κ²μ Multi Thread Applicationμ΄λΌκ³ νλ€.
Demon Thread
main μ°λ λμ μμ μ 보쑰νλ μν μ νλ€.
κ·Έλ κΈ°μ main μ°λ λκ° μ’ λ£λλ©΄ ν¨κ» μ’ λ£κ° λλ€.
(μμ μ½λ)
(μ€ν κ²°κ³Ό)
λκΈ°ν (Synchronize)
μκ³ μμ(Critical section) κ³Ό μ κΈ(lock)
곡μ λ°μ΄ν°λ₯Ό μ¬μ©νλ μ½λ μμμ μκ³ μμμΌλ‘ μ§μ ν΄λκ³ , 곡μ λ°μ΄ν°(κ°μ²΄)κ° κ°μ§κ³ μλ lockμ νλν λ¨ νλμ μ°λ λλ§ μ΄ μμ λ΄μ μ½λλ₯Ό μνν μ μλλ‘ νλ€. κ·Έλ¦¬κ³ ν΄λΉ μ°λ λκ° μκ³ μμ λ΄μ λͺ¨λ μ½λλ₯Ό μννκ³ λ²μ΄λμ lockμ λ°λ©ν΄μΌλ§ λ€λ₯Έ μ°λ λκ° λ°λ©λ lockμ νλνμ¬ μκ³ μμμ μ½λλ₯Ό μνν μ μκ² λλ€.
μ¬λ¬ κ°μ μ°λ λκ° ν κ°μ 리μμ€λ₯Ό μ¬μ©νλ €κ³ ν λ, μ¬μ©νλ €λ μ°λ λλ₯Ό μ μΈν λλ¨Έμ§λ€μ μ κ·Όνμ§ λͺ»νκ² λ§λ κ²μ΄λ€.
-> Thread Safe (μ°λ λ μμ νλ€) , νμ§λ§ λ무 λ¨λ°ν΄μ μ¬μ©νλ©΄ μ±λ₯ μ νλ₯Ό μΌμΌν¬ μ μμ.
Synchronized μ¬μ©λ² 2κ°μ§
- λ©μλμμ μ¬μ© (λ©μλ μ 체λ₯Ό μκ³ μμμΌλ‘ μ§μ )
public synchronized void method() { }
- κ°μ²΄ λ³μμ μ¬μ© (λ½μ κ±Έκ³ μνλ κ°μ²΄λ₯Ό μ°Έμ‘°νλ κ²μ΄μ¬μΌνλ€.)
private Object o = new Object();
public void method() {
synchronized (o) {
// ...
}
}
(μμ μ½λ) - synchronized λ―Έ μ μ©
- Account ν΄λμ€
- Test ν΄λμ€
- μ€νκ²°κ³Ό
κ³μ’ μμ‘λ³΄λ€ μ§λΆνλ κΈμ‘μ΄ λ ν¬λ©΄, μ§λΆνμ§ μλλ‘ μ€μ νμλλ°, λ¨μ κΈμ‘μ΄ -100μ΄ λμλ€.
μ¬κΈ°μ λ©ν°μ€λ λμ λ¬Έμ μ μ΄ λ°κ²¬λλ κ²μ΄λ€. Thread-safe νμ§ μκΈ° λλ¬Έμ Thread-0μ΄ sleepμμ κΉ¨μ΄λκΈ°λ μ μ Thread-1κ° μΆκΈμ ν΄λ²λ¦° κ²μ΄λ€. μ΄μ synchronizedλ₯Ό λ©μλμ λΆμ¬μ£Όλ©΄ μ½κ² ν΄κ²°μ΄ λλ€!
(μμ μ½λ) - Synchronized μ μ©
- Account ν΄λμ€
- Test ν΄λμ€ λμΌ (μλ΅)
- μ€νκ²°κ³Ό
λ°λλ½ (DeadLock, κ΅μ°©μν)
κ΅μ°©μνλ, λ μ΄μμ μ°λ λκ° lockμ νλνκΈ° μν΄ λκΈ°νλλ°. μ΄ lockμ μ‘κ³ μλ μ°λ λλ€λ λκ°μ΄ λ€λ₯Έ lockμ κΈ°λ€λ¦¬λ©΄μ μλ‘ block μνμ λμ΄λ κ²μ λ§νλ€. λ°λλ½μ λ€μμ μ°λ λκ° κ°μ lockμ λμμ, λ€λ₯Έ λͺ λ Ήμ μν΄ νλνλ € ν λ λ°μν μ μλ€.
μμ) Thread-1μ΄ Aμ lockμ κ°μ§κ³ μλ μνμμ Bμ lockμ νλνλ € νλ€. κ·Έλ¦¬κ³ Thread-2κ° Bμ lockμ κ°μ§κ³ μλ μνμμ Aμ lockμ νλνλ € νλ€. -> λ°λλ½μ΄ μκΈ΄λ€. (λ λ€ μλ‘κ° νλνλ €λ A, B μ lockμ μμν νλν μ μλ€.)
(μμ μ½λ)
public class Test{
static final Object lock_1 = new Object();
static final Object lock_2 = new Object();
private static class Sample1 extends Thread {
@Override
public void run() {
synchronized (lock_1) {
System.out.println("Thread 1 : Holding lock 1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("Thread 1 : Wating for lock 2");
synchronized (lock_2) {
System.out.println("Thread 1 : Holding lock 1 & 2");
}
}
}
}
private static class Sample2 extends Thread {
@Override
public void run() {
synchronized (lock_2) {
System.out.println("Thread 2 : Holding lock 1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("Thread 2 : Wating for lock 2");
synchronized (lock_1) {
System.out.println("Thread 2 : Holding lock 1 & 2");
}
}
}
}
public static void main(String[] args) {
Sample1 thread1 = new Sample1();
Sample2 thread2 = new Sample2();
thread1.start();
thread2.start();
}
}
// μ€νκ²°κ³Ό
Thread 1 : Holding lock 1
Thread 2 : Holding lock 1
Thread 1 : Wating for lock 2
Thread 2 : Wating for lock 1
μλ‘μ lockμ μ»μΌλ €κ³ νΈμΆνκΈ° λλ¬Έμ 무νμ λ°λλ½μ λΉ μ§κ² λλ€.
REFERENCES
tutorials.jenkov.com/java-concurrency/deadlock.html
docs.oracle.com/javase/tutorial/essential/concurrency/sleep.html
codechacha.com/ko/java-synchronized-keyword/