λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
κΈ€μ“°λŠ” κΏ€λ²Œ 🐝

Dev Study #2 (feat. JAVA)

by soyλ―Έλ‹ˆ 2022. 2. 18.

 

 

[μžλ°” μ–Έμ–΄λ‘œ λ°°μš°λŠ” λ””μžμΈ νŒ¨ν„΄ μž…λ¬Έ] λ„μ„œλ₯Ό 읽고 κ³΅λΆ€ν•œ λ‚΄μš©μž…λ‹ˆλ‹€.

 

 

 

UML (Undefined Modeling Language)

μ‹œμŠ€ν…œμ„ μ‹œμƒν™”ν•˜λŠ” λ°©λ²•μ΄λ‚˜ 섀계λ₯Ό λ¬Έμ„œν™”ν•˜κΈ° μœ„ν•œ ν‘œν˜„ 방법 (ex. 클래슀 λ‹€μ΄μ–΄κ·Έλž¨)

 

 

μ“°λ ˆλ“œ (Thread)

ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰ν•˜κ³  μžˆλŠ” 주체

 

 

μ‹±κΈ€ μ“°λ ˆλ“œ ν”„λ‘œκ·Έλž¨ (Single Thread Program)

ν”„λ‘œκ·Έλž¨ μ²˜λ¦¬κ°€ ν•˜λ‚˜μ˜ νλ¦„μœΌλ‘œ μ΄μ–΄μ§€λŠ” ν”„λ‘œκ·Έλž¨

μ–΄λ–€ μ‹œμ μ— μ‹€ν–‰λ˜κ³  μžˆλŠ” μ²˜λ¦¬λŠ” ν•˜λ‚˜μ΄λ‹€.

 

 

메인 μ“°λ ˆλ“œ (Main Thread)

λͺ…λ Ήμ–΄ μ€„μ—μ„œ μ§€μ •ν•œ 클래슀의 main λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰

 

 

λ©€ν‹° μ“°λ ˆλ“œ ν”„λ‘œκ·Έλž¨ (Multithreaded Program)

볡수의 μ“°λ ˆλ“œκ°€ λ™μž‘ν•˜λŠ” ν”„λ‘œκ·Έλž¨ (μžλ°”λŠ” default 둜 λ©€ν‹° μ“°λ ˆλ“œ μ μš©λ˜μ–΄ μžˆλ‹€.)

 

 

 

Thread 클래슀

  • run λ©”μ†Œλ“œ : μƒˆλ‘œμš΄ μ“°λ ˆλ“œκ°€ κΈ°λ™λ˜λ©΄ run λ©”μ†Œλ“œ 호좜
public class PrintThread extends Thread {
    private String msg;
    public PrintThread(String msg){
    	this.msg = msg;
    }
    public void run() {
        for (int i = 0; i< 10000; i++){
           System.out.print(msg);
        }
    }
}

 

  • start λ©”μ†Œλ“œ : μƒˆλ‘œμš΄ μ“°λ ˆλ“œ 기동
public class Main {
	public static void main(String[] args){
    	MyThread t = new MyThread();
        t.start();
        for(int i = 0; i < 10000; i++){
        	System.out.print("Good!");
        }
    }
}

 

 

μ“°λ ˆλ“œ 기동 방법

  • Thread 클래슀의 μ„œλΈŒ 클래슀 (run, start) μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš© (μœ„μ˜ μ˜ˆμ‹œ μ°Έκ³ )
  • Runnable μΈν„°νŽ˜μ΄μŠ€μ˜ κ΅¬ν˜„ 클래슀 μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©

 

Thread μ„œλΈŒ 클래슀 μ‚¬μš©

public class Main {
    public static void main(String[] args){
        new PrintThread("Good!").start();
        new PrintThread("Nice!").start();
    }
}

 

  • start λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜κΈ° μ „κΉŒμ§€λŠ” μΈμŠ€ν„΄μŠ€λŠ” λ§Œλ“€μ–΄μ§€κ³  μžˆλ”λΌλ„ μ“°λ ˆλ“œλŠ” κΈ°λ™ν•˜μ§€ μ•ŠλŠ”λ‹€.

 

 

Runnable μΈν„°νŽ˜μ΄μŠ€ μ‚¬μš©

public interface Runnable {
     public abstract void run();
}

public class Printer implements Runnable {
     private String msg;
     public Printer(String msg){
           this.msg = msg;
     }
     public void run() {
          for (int i = 0; i < 10000; i++){
              System.out.print(msg);
          }
     }
}

public class Main {
    public static void main(String[] args){
         new Thread(new Printer("Good!")).start();
         new Thread(new Printer("Nice!")).start();
    }
}

 

  • Runnable μΈν„°νŽ˜μ΄μŠ€μ—μ„œ run λ©”μ†Œλ“œ κ΅¬ν˜„
  • Printer ν΄λž˜μŠ€μ—μ„œ Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ°Έμ‘°ν•˜μ—¬ run λ©”μ†Œλ“œλ₯Ό μ™„μ„±ν•˜κ³  start λ©”μ†Œλ“œλ‘œ μ“°λ ˆλ“œ 기동

 

 

Thread μΌμ‹œ 정지

sleep λ©”μ†Œλ“œ

  • Thread.sleep(1000) : μ•½ 1000 밀리 초 (= 1초) κ°„ ν˜„μž¬ μ“°λ ˆλ“œ μΌμ‹œ 정지
  • try-catch λ¬Έ μ•ˆμ—μ„œ μ‚¬μš© -> interruptedException μ˜ˆμ™Έ 처리
  • interruptedException : μ“°λ ˆλ“œ 처리λ₯Ό μ·¨μ†Œν•˜κΈ° μœ„ν•΄μ„œ μ“°μ΄λŠ” μ˜ˆμ™Έ 처리

 

 

Thread 배타 μ œμ–΄

μ“°λ ˆλ“œ A 와 μ“°λ ˆλ“œ B κ°€ λ³‘ν–‰ν•΄μ„œ λ™μž‘ν•˜λŠ” 경우, μ“°λ ˆλ“œ A 의 처리 사이에 μ“°λ ˆλ“œ  B 의 μ²˜λ¦¬κ°€ λΌμ–΄λ“€κ²Œ 될 κ°€λŠ₯성이 μžˆλ‹€.

이렇듯 ν•˜λ‚˜μ˜ μ“°λ ˆλ“œκ°€ μ–΄λ–€ 처리λ₯Ό μ‹€ν–‰ν•˜κ³  μžˆμ„ λ•Œ λ‹€λ₯Έ μ“°λ ˆλ“œλŠ” κ·Έ 뢀뢄을 μ‹€ν–‰ν•  수 없도둝 μ œμ–΄ν•  ν•„μš”κ°€ μžˆλŠ”λ° 이λ₯Ό 배타 μ œμ–΄ (μƒν˜Έ 배타, synchronized) 라고 ν•œλ‹€.

 

 

synchronized λ©”μ†Œλ“œ (= 동기 λ©”μ†Œλ“œ)

λ©”μ†Œλ“œμ— synchronized λ₯Ό λΆ™μ—¬μ„œ μ„ μ–Έν•˜λ©΄ ν•΄λ‹Ή λ©”μ†Œλ“œλŠ” ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ‘œ λ™μž‘ν•˜κ²Œ λœλ‹€.

ν•œ λ²ˆμ— ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ§Œ μ‹€ν–‰μ‹œν‚¬ 수 μžˆλ‹€.

 

public class Bank {
    private int money;
    private String name;
    
    public Bank(String name, int money){
       this.name = name;
       this.money = money;
    }
    
    // μž…κΈˆ
    public synchronized void deposit(int m){
       money += m;
    }
    
    // 좜금
    public synchronized boolean withdraw(int m){
       if (money >=m ){
          money -= m;
          return true;  // 인좜 κ°€λŠ₯
       } else {
          return false; // 인좜 λΆˆκ°€ (μž”κ³  λΆ€μ‘±)
       }
    }
    
    public String getName(){
       return name;
    }
}

 

  • deposit λ©”μ†Œλ“œμ™€ withdraw λ©”μ†Œλ“œλŠ” synchronized λ©”μ†Œλ“œλ‘œ ν•œ λ²ˆμ— ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ§Œ μ‹€ν–‰κ°€λŠ₯ν•˜λ―€λ‘œ ν˜„μž¬ μ‹€ν–‰λ˜κ³  μžˆλŠ” μ“°λ ˆλ“œκ°€ 있으면 λ‹€λ₯Έ μ“°λ ˆλ“œλŠ” λŒ€κΈ°ν•΄μ•Ό ν•œλ‹€. (μ“°λ ˆλ“œκ°€ 싀행을 μ™„λ£Œν•  λ•ŒκΉŒμ§€ synchronized λ©”μ†Œλ“œμ— 락이 κ±Έλ¦°λ‹€.)
  • synchronized κ°€ μ•„λ‹Œ λ©”μ†Œλ“œμ— κ΄€ν•΄μ„œλŠ” λ™μ‹œμ— 두 개 μ΄μƒμ˜ μ“°λ ˆλ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆλ‹€.

 

 

synchronized ν•œ 클래슀 λ©”μ†Œλ“œ / synchronized 블둝

// synchronized ν•œ μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œ (블둝)

class Something {
	static synchronized void method() {
        ...
    }
}

class Something {
      void method() {
         synchronized (this){
            ...
         }
    }
}



// synchronized 클래슀 λ©”μ†Œλ“œ

class Something {
	static void method() {
        synchronized (Something.class){
           ...
        }
    }
}

 

  • synchronized ν•œ μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œμ—μ„œλŠ” μ“°λ ˆλ“œμ˜ 배타 μ œμ–΄λ₯Ό μœ„ν•΄ this 의 락이 μ‚¬μš©λœλ‹€.
  • synchronized 클래슀 λ©”μ†Œλ“œμ—μ„œλŠ” μ“°λ ˆλ“œμ˜ 배타 μ œμ–΄λ₯Ό μœ„ν•΄ ν•΄λ‹Ή 클래슀의 클래슀 객체 락이 μ‚¬μš©λœλ‹€.

 

 

 

Thread 의 ν˜‘μ‘°

wait μ…‹ (μ“°λ ˆλ“œ λŒ€ν•©μ‹€)

  • ν•΄λ‹Ή μΈμŠ€ν„΄μŠ€μ˜ wait λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•œ ν›„ λ™μž‘μ„ μ •μ§€ν•˜κ³  μžˆλŠ” μ“°λ ˆλ“œμ˜ 집합
  • λͺ¨λ“  μΈμŠ€ν„΄μŠ€λŠ” wait 셋을 가진닀.
  • wait λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ λ™μž‘μ„ μΌμ‹œμ •μ§€ ν•œ μ“°λ ˆλ“œκ°€ wait 셋에 λ“€μ–΄κ°€μ„œ 무언가 λ°œμƒν•˜κΈ° μ „κΉŒμ§€ 계속 μžˆλŠ”λ‹€.

 

 

wait λ©”μ†Œλ“œ _ μ“°λ ˆλ“œλ₯Ό wait 셋에 λ„£λŠ”λ‹€.

// μ“°λ ˆλ“œκ°€ μΈμŠ€ν„΄μŠ€ obj 의 wait 셋에 λ“€μ–΄κ°„λ‹€. (= μ“°λ ˆλ“œκ°€ obj μƒμ—μ„œ wait ν•˜κ³  μžˆλ‹€.)
obj.wait();

// μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œ μ•ˆμ— wait λ©”μ†Œλ“œκ°€ 있으면 μ“°λ ˆλ“œλŠ” this 의 wait 셋에 λ“€μ–΄κ°€μ„œ this 상에 wait ν•˜κ²Œ λœλ‹€.
wait(); 
// this.wait();
  • wait λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° μœ„ν•΄μ„œλŠ” μ“°λ ˆλ“œκ°€ 락을 가지고 μžˆμ–΄μ•Ό ν•œλ‹€.
  • κ·ΈλŸ¬λ‚˜ wait 셋에 λ“€μ–΄κ°ˆ λ•Œ μ“°λ ˆλ“œλŠ” ν•΄λ‹Ή μΈμŠ€ν„΄μŠ€μ˜ 락을 ν•΄μ œν•œλ‹€.

 

notify λ©”μ†Œλ“œ _ ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ₯Ό wait μ…‹μ—μ„œ κΊΌλ‚Έλ‹€. (κΉ¨μš΄λ‹€)

// obj 의 wait 셋에 μžˆλŠ” μ“°λ ˆλ“œ ν•˜λ‚˜λ₯Ό κΊΌλ‚Έλ‹€.
obj.notify();
  • μ–΄λ–€ μΈμŠ€ν„΄μŠ€μ˜ wait 셋에 μžˆλŠ” μ“°λ ˆλ“œ μ€‘μ—μ„œ ν•˜λ‚˜λ₯Ό μ„ νƒν•˜μ—¬ κΊΌλ‚Έλ‹€.
  • notify λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° μœ„ν•΄ wait λ©”μ†Œλ“œμ™€ λ§ˆμ°¬κ°€μ§€λ‘œ μ“°λ ˆλ“œκ°€ λΆˆλŸ¬λ‚Έ μΈμŠ€ν„΄μŠ€μ˜ 락을 가지고 μžˆμ–΄μ•Ό ν•œλ‹€.
  • μˆœμ„œ : wait μ…‹μ—μ„œ μ“°λ ˆλ“œ A κ°€ λ‚˜μ˜΄ -> notify λ₯Ό μ‹€ν–‰μ‹œν‚¨ μ“°λ ˆλ“œ B κ°€ 락을 ν•΄μ œ -> μ“°λ ˆλ“œ A κ°€ 락을 κ°€μ§€κ²Œ 되고 wait λ‹€μŒ μˆœμ„œλ‘œ λ„˜μ–΄κ°

 

notifyAll λ©”μ†Œλ“œ _ λͺ¨λ“  μ“°λ ˆλ“œλ₯Ό wait μ…‹μ—μ„œ κΊΌλ‚Έλ‹€. (κΉ¨μš΄λ‹€)

// wait 셋에 μžˆλŠ” λͺ¨λ“  μ“°λ ˆλ“œλ₯Ό wait μ…‹μ—μ„œ κΊΌλ‚Έλ‹€.
// obj λΌλŠ” μΈμŠ€ν„΄μŠ€μ˜ wait μ…‹ 속에 있던 μ“°λ ˆλ“œλ“€ 전원을 흔듀어 κΉ¨μš΄λ‹€.

obj.notifyAll();

// ν•΄λ‹Ή λ©”μ†Œλ“œμ˜ μΈμŠ€ν„΄μŠ€(this) wait μ…‹ 속에 μžˆλŠ” μ“°λ ˆλ“œλ“€μ„ λͺ¨λ‘ wait μ…‹μ—μ„œ κΊΌλ‚Έλ‹€.
notifyAll(); // this.notifyAll();

 

락을 가지고 μžˆμ§€ μ•Šμ€ μ“°λ ˆλ“œκ°€ wait, notify, notifyAll λ©”μ†Œλ“œλ₯Ό λΆˆλŸ¬λ‚΄λ©΄?

  • μ˜ˆμ™Έ java.lang.IllegalMonitorStateException 이 λ˜μ Έμ§„λ‹€.

 

 

 

 

 

'κΈ€μ“°λŠ” κΏ€λ²Œ 🐝' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

Dev Study #4 (feat. Design Pattern)  (0) 2022.02.21
Dev Study #3 (feat. Design Pattern)  (0) 2022.02.18
Dev Study #1  (0) 2022.02.16
[Book Review] 인생은 싀전이닀  (0) 2021.10.07

λŒ“κΈ€