SSARTEL-10th / JPTS_bookstudy

"κ°œλ°œμžκ°€ λ°˜λ“œμ‹œ μ•Œμ•„μ•Ό ν•  μžλ°” μ„±λŠ₯ νŠœλ‹ 이야기" μ™„μ „ 정볡
7 stars 0 forks source link

synchronized! 동적 정적 include! #27

Open olrlobt opened 11 months ago

olrlobt commented 11 months ago

πŸ‘ 문제

24μž₯ μ •λ¦¬λœ λ‚΄μš©μ„ λ³΄λ‹€λ³΄λ‹ˆ, 웬걸! 배운 것 같은 λ‚΄μš©μΈλ° 머릿속에 ?κ°€ 가득 생겼닀.


ν•„μš”ν•œλΆ€λΆ„μ—synchronized λΈ”λ‘μ„μ‚¬μš©ν•˜μ˜€λŠ”κ°€?
κ·Έλƒ₯ λ™μ‹œμ—ν•΄λ‹Ήλ©”μ„œλ“œκ°€ ν˜ΈμΆœλ κ²ƒκ°™μ•„μ„œsynchronized λΈ”λ‘μ„μ‚¬μš©ν•œ
κ²ƒμ€μ•„λ‹Œμ§€ν™•μΈν•΄μ•Όν•œλ‹€. ν•„μš”μ—†λŠ”λΆ€λΆ„μ—synchronized λΈ”λ‘μ„μ‚¬μš©ν•˜ 게될 경우 μ„±λŠ₯μ €ν•˜λ₯Όλ°œμƒμ‹œν‚¬μˆ˜μžˆλ‹€.

JSP의includeλŠ”λ™μ μœΌλ‘œν–ˆλŠ”κ°€?μ•„λ‹ˆλ©΄μ •μ μœΌλ‘œν–ˆλŠ”κ°€?
JSPλ₯Ό λ™μ μœΌλ‘œincludeν•˜λ©΄ μ„œλ²„μ—λ„ λΆ€ν•˜λ₯Όμ€„ λΏλ§Œμ•„λ‹ˆλΌ 응닡 μ‹œκ°„μ—
λ„μ˜ν–₯을쀀닀. κΌ­ν•„μš”ν•œλΆ€λΆ„μ—λ§Œλ™μ includeλ₯Όν•˜κΈ°λ°”라며, κ·Έλ ‡μ§€μ•Š 은 κ²½ 우 에 λŠ” μ • 적 i n c l u d e 의 사 용 을 ꢌ μž₯ ν•œ λ‹€ . κ·Έλ ‡ λ‹€ κ³  무 μ‘° 건 μ • 적 으 둜
include λ₯Όν•˜λ©΄λ³€μˆ˜λ₯Ό κ³΅μœ ν•˜κ²Œλ˜μ–΄μ˜ˆκΈ°μΉ˜λͺ»ν•œλ¬Έμ œκ°€λ°œμƒν• μˆ˜ μžˆμœΌλ―€ 둜 유 의 ν•΄ μ„œ 사 용 ν•˜ κΈ° λ°” λž€ λ‹€.

μœ„ λ‚΄μš©λ“€μ„ μ˜ˆμ œμ™€ ν•¨κ»˜ 이유λ₯Ό μ„€λͺ…ν•΄μ£Όλ©΄ 쒋을 것 κ°™λ‹€!

✈️ μ„ μ • λ°°κ²½

λ‚΄ λ¨Έλ¦Ώμ†μ˜ μ§€μš°κ°œ

πŸ“Ί κ΄€λ ¨ 챕터 및 레퍼런슀

κ΄€λ ¨ 챕터와 좜처λ₯Ό μ μ–΄μ£Όμ„Έμš”

story. 24 425p.

🐳 λΉ„κ³ 

KIMSEI1124 commented 11 months ago

λ“€μ–΄κ°€λ©°

Javaλ₯Ό 곡뢀할 λ•Œ synchronized ν‚€μ›Œλ“œκ°€ μ‘΄μž¬ν•˜λŠ” 것은 μ•Œκ³  μžˆμ—ˆμŠ΅λ‹ˆλ‹€! ν•˜μ§€λ§Œ λ”±νžˆ μ‚¬μš©ν•˜μ§€ μ•Šμ•„ μžμ„Ένžˆ λͺ°λžλŠ”데 ν•΄λ‹Ή κΈ°νšŒκ°€ λ˜μ–΄μ„œ 쑰사λ₯Ό ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

Synchronized

μžλ°”μ—μ„œ λ©€ν‹°μŠ€λ ˆλ“œλ₯Ό μ΄μš©ν•˜λ©΄ μ—¬λŸ¬μž‘μ—…μ„ λ™μ‹œμ— μ²˜λ¦¬ν•  수 있기 λ•Œλ¬Έμ— μž‘μ—…νš¨μœ¨μ΄ μ’‹μ•„μ§‘λ‹ˆλ‹€. ν•˜μ§€λ§Œ ν•˜λ‚˜μ˜ κ³΅μœ μžμ›μ„ μ—¬λŸ¬ μŠ€λ ˆλ“œμ—μ„œ λ™μ‹œμ— μ ‘κ·Όν•˜μ—¬ μ‚¬μš©ν•˜κ²Œ 되면 λ•Œλ•Œλ‘œ μ˜ˆμƒμΉ˜ λͺ»ν•œ κ²°κ³Όκ°€ λ‚˜νƒ€λ‚˜κ²Œ λ©λ‹ˆλ‹€. μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λŠ” synchronized 에 λŒ€ν•΄μ„œ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

μžλ°”μ—μ„œ μ§€μ›ν•˜λŠ” synchroized ν‚€μ›Œλ“œλŠ” μ—¬λŸ¬κ°œμ˜ μŠ€λ ˆλ“œκ°€ ν•œκ°œμ˜ μžμ›μ„ μ‚¬μš©ν•˜κ³ μž ν•  λ•Œ, ν˜„μž¬ 데이터λ₯Ό μ‚¬μš©ν•˜κ³  μžˆλŠ” ν•΄λ‹Ή μŠ€λ ˆλ“œλ₯Ό μ œμ™Έν•˜κ³  λ‚˜λ¨Έμ§€ μŠ€λ ˆλ“€μ€ 데이터에 μ ‘κ·Ό ν•  수 없도둝 λ§‰λŠ” κ°œλ…μž…λ‹ˆλ‹€.

ν•΄λ‹Ή ν‚€μ›Œλ“œλŠ” λ³€μˆ˜λ‚˜ ν•¨μˆ˜μ— μ‚¬μš©ν•΄μ„œ 동기화할 수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ Synchroinzed λ₯Ό λ‚¨λ°œν•˜λ©΄ 였히렀 ν”„λ‘œκ·Έλž¨ μ„±λŠ₯μ €ν•˜λ₯Ό μΌμœΌν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έ μ΄μœ λŠ” μžλ°” λ‚΄λΆ€μ μœΌλ‘œ λ©”μ„œλ“œλ‚˜ λ³€μˆ˜μ— 동기화λ₯Ό ν•˜κΈ° μœ„ν•΄ block 와 unblock 을 μ²˜λ¦¬ν•˜κ²Œ λ˜λŠ”λ° 이런 μ²˜λ¦¬κ°€ λ§Žμ΄μ§€κ²Œ 되면 였히렀 ν”„λ‘œκ·Έλž¨ μ„±λŠ₯μ €ν•˜λ₯Ό μΌμœΌν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

μ‚¬μš© 방법

Non Synchronized


λ¨Όμ € synchronized κ°€ ν•„μš”ν•œ 이유λ₯Ό 예제 μ½”λ“œλ‘œ μ•Œμ•„λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

Main

package thread;  

import thread.obj.Task;  

public class SynchronizedStudy {  
    public static void main(String[] args) {  
        Task task = new Task();  
        Thread threadOne = new Thread(task);  
        Thread threadTwo = new Thread(task);  

        threadOne.setName("Thread One");  
        threadTwo.setName("Thread Two");  

        threadOne.start();  
        threadTwo.start();  
    }  
}

Task λ₯Ό μ΄ˆκΈ°ν™” ν•œ λ’€ Threadλ₯Ό 2개 μƒμ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 각 μŠ€λ ˆλ“œμ˜ 이름을 μ„€μ •ν•œ λ’€ μ‹€ν–‰ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

Task

package thread.obj;  

import java.util.Random;  

public class Task implements Runnable {  

    private final Random random;  
    Account account = new Account();  

    public Task() {  
        random = new Random();  
        random.setSeed(System.currentTimeMillis()); // `seed`λ₯Ό 랜덀으둜 μ„€μ •  
    }  

    @Override  
    public void run() {  
        while (account.canWithDraw()) {  
            int money = (random.nextInt(3) + 1) * 100;  
            account.withDraw(money);  
        }  
    }  
}

Task μŠ€λ ˆλ“œμž…λ‹ˆλ‹€. Runnable λ₯Ό implements ν•˜μ—¬ run() 을 Override ν•˜μ˜€μŠ΅λ‹ˆλ‹€. Moneyλ₯Ό 100, 200, 300 쀑 ν•˜λ‚˜μ˜ 값을 가져와 Account의 withDrawλ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€.

Account

package thread.obj;  

public class Account {  
    private int balance = 1000;  

    public void withDraw(int money) {  
        if (canWithDrawByMoney(money)) {  
            try {  
                String threadName = Thread.currentThread().getName();  
                System.out.println(threadName + ") 좜금 κΈˆμ•‘ : [" + money + "]");  
                Thread.sleep(1000);  
                balance -= money;  
                System.out.println(threadName + ") balance : [" + balance + "]");  
            } catch (InterruptedException e) {  
                System.out.println(e.getMessage());  
                Thread.currentThread().interrupt();  
            }  
        }  
    }  

    private boolean canWithDrawByMoney(int money) {  
        return balance >= money;  
    }  

    public boolean canWithDraw() {  
        return balance > 0;  
    }  
}

λ‹¨μˆœνžˆ balance λ₯Ό money 만큼 μ€„μ—¬μ£ΌλŠ” 단계 μž…λ‹ˆλ‹€.

μ‹€ν–‰ κ²°κ³Ό

Thread One) 좜금 κΈˆμ•‘ : [100]
Thread Two) 좜금 κΈˆμ•‘ : [100]
Thread Two) balance : [900]
Thread Two) 좜금 κΈˆμ•‘ : [300]
Thread One) balance : [800]
Thread One) 좜금 κΈˆμ•‘ : [100]
Thread One) balance : [700]
Thread One) 좜금 κΈˆμ•‘ : [300]
Thread Two) balance : [400]
Thread Two) 좜금 κΈˆμ•‘ : [300]
Thread One) balance : [100]
Thread One) 좜금 κΈˆμ•‘ : [100]
Thread Two) balance : [-200]
Thread One) balance : [-300]

κ²°κ³Ό 화면을 보면 μž”μ•‘μ΄ 0이 될 λ•ŒκΉŒμ§€ μΆœκΈˆμ„ ν•΄μ•Όν•˜λŠ”λ° μž”μ•‘μ΄ λ§ˆμ΄λ„ˆμŠ€κ°€ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

μ—¬κΈ°μ„œ λ©€ν‹°μŠ€λ ˆλ“œμ˜ 문제점이 λ°œκ²¬λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 이유둜 thread-safeν•˜κΈ° μœ„ν•΄μ„œ synchronized ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜κ²Œλ©λ‹ˆλ‹€.

Synchronized


κ³΅μœ λ°μ΄ν„°μ— λŒ€ν•œ μ ‘κ·Όκ³Ό μˆ˜μ •μ΄ μ΄λ£¨μ–΄μ§€λŠ” λ©”μ„œλ“œμ— synchronized ν‚€μ›Œλ“œλ₯Ό λ¦¬ν„΄νƒ€μž… μ•žμ— λΆ™μ—¬ μ£Όλ©΄ μœ„μ˜ μ˜ˆμ œλŠ” ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

package thread.obj;  

public class Account {  
    private int balance = 1000;  

    public synchronized void withDraw(int money) {  
        if (canWithDrawByMoney(money)) {  
            try {  
                String threadName = Thread.currentThread().getName();  
                System.out.println(threadName + ") 좜금 κΈˆμ•‘ : [" + money + "]");  
                Thread.sleep(1000);  
                balance -= money;  
                System.out.println(threadName + ") balance : [" + balance + "]");  
            } catch (InterruptedException e) {  
                System.out.println(e.getMessage());  
                Thread.currentThread().interrupt();  
            }  
        }  
    }

  ...
}

μ‹€ν–‰ κ²°κ³Ό

Thread One) 좜금 κΈˆμ•‘ : [100]
Thread One) balance : [900]
Thread One) 좜금 κΈˆμ•‘ : [200]
Thread One) balance : [700]
Thread Two) 좜금 κΈˆμ•‘ : [200]
Thread Two) balance : [500]
Thread Two) 좜금 κΈˆμ•‘ : [100]
Thread Two) balance : [400]
Thread Two) 좜금 κΈˆμ•‘ : [200]
Thread Two) balance : [200]
Thread Two) 좜금 κΈˆμ•‘ : [200]
Thread Two) balance : [0]

synchronizedλ₯Ό μ‚¬μš©ν•˜μ—¬ thread-safeλ₯Ό μ‹œμΌ°κΈ° λ•Œλ¬Έμ— λ°μ΄ν„°λ‚˜ λ©”μ„œλ“œ μ μœ ν•˜κ³  μžˆλŠ” μŠ€λ ˆλ“œκ°€ μ˜¨μ „νžˆ μžμ‹ μ˜ μž‘μ—…μΌ 마칠 수 μ΄μŠ΅λ‹ˆλ‹€.

μ‚¬μš© κ°€λŠ₯ν•œ 블둝

synchronized ν‚€μ›Œλ“œλŠ” λ‹€μŒκ³Ό 같은 μœ ν˜•μ—μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œ


μœ„μ˜ μ˜ˆμ œμ—μ„œ μ‚¬μš©ν•œ λ°©μ‹μž…λ‹ˆλ‹€.

μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œμ˜ λ™κΈ°ν™”λŠ” 이 λ©”μ†Œλ“œλ₯Ό 가진 μΈμŠ€ν„΄μŠ€λ₯Ό κΈ°μ€€μœΌλ‘œ μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ, ν•œ ν΄λž˜μŠ€κ°€ λ™κΈ°ν™”λœ μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œλ₯Ό 가진닀면, μ—¬κΈ°μ„œ λ™κΈ°ν™”λŠ” 이 클래슀의 ν•œ μΈμŠ€ν„΄μŠ€λ₯Ό κΈ°μ€€μœΌλ‘œ μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€. 그리고 ν•œ μ‹œμ μ— 였직 ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ§Œμ΄ λ™κΈ°ν™”λœ μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ •λ¦¬ν•˜λ©΄ λ‘˜ μ΄μƒμ˜ μΈμŠ€ν„΄μŠ€κ°€ μžˆλ‹€λ©΄, ν•œ μ‹œμ μ— ν•œ μΈμŠ€ν„΄μŠ€μ— ν•œ μ“°λ ˆλ“œλ§Œ 이 λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

μŠ€νƒœν‹± λ©”μ†Œλ“œ


μŠ€νƒœν‹± λ©”μ†Œλ“œμ˜ λ™κΈ°ν™”λŠ” μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œμ™€ 같은 λ°©μ‹μœΌλ‘œ μ΄λ£¨μ–΄μ§€μ§€λ§Œ JVMμ•ˆμ— 클래슀 κ°μ²΄λŠ” ν΄λž˜μŠ€λ‹Ή ν•˜λ‚˜λ§Œ μ‘΄μž¬ν•  수 μžˆμœΌλ―€λ‘œ, 같은 ν΄λž˜μŠ€μ— λŒ€ν•΄μ„œ 였직 ν•œ μ“°λ ˆλ“œλ§Œ μŠ€νƒœν‹± λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

만일 λ™κΈ°ν™”λœ μŠ€νƒœν‹± λ©”μ†Œλ“œκ°€ λ‹€λ₯Έ ν΄λž˜μŠ€μ— 각각 μ‘΄μž¬ν•œλ‹€λ©΄, μ“°λ ˆλ“œλŠ” 각 클래슀의 λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

package thread.obj;  

public class Account {  
    private static int balance = 1000;  

    public static synchronized void withDraw(int money) {  
        if (canWithDrawByMoney(money)) {  
            try {  
                String threadName = Thread.currentThread().getName();  
                System.out.println(threadName + ") 좜금 κΈˆμ•‘ : [" + money + "]");  
                Thread.sleep(1000);  
                balance -= money;  
                System.out.println(threadName + ") balance : [" + balance + "]");  
            } catch (InterruptedException e) {  
                System.out.println(e.getMessage());  
                Thread.currentThread().interrupt();  
            }  
        }  
    }  

    ...
}

μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œ μ•ˆμ˜ 동기화 블둝


λ©”μ†Œλ“œ μ•ˆμ— 동기화 블둝을 λ”°λ‘œ μž‘μ„±ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

동기화 블둝이 κ΄„ν˜Έ μ•ˆμ— ν•œ 객체λ₯Ό 전달받고 μžˆμŠ΅λ‹ˆλ‹€. μ˜ˆμ œμ—μ„œλŠ” thisκ°€ μ‚¬μš©λ˜μ—ˆλŠ”λ° withDraw() λ©”μ†Œλ“œκ°€ 호좜된 객체λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. 이 동기화 블둝 μ•ˆμ— μ „λ‹¬λœ 객체λ₯Ό λͺ¨λ‹ˆν„° 객체라 ν•©λ‹ˆλ‹€. 이 μ½”λ“œλŠ” λͺ¨λ‹ˆν„° 객체λ₯Ό κΈ°μ€€μœΌλ‘œ 동기화가 이루어지고 μžˆμŠ΅λ‹ˆλ‹€.

같은 λͺ¨λ‹ˆν„° 객체λ₯Ό κΈ°μ€€μœΌλ‘œ λ™κΈ°ν™”λœ 블둝 μ•ˆμ˜ μ½”λ“œλ₯Ό 였직 ν•œ μ“°λ ˆλ“œλ§Œμ΄ μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

package thread.obj;  

public class Account {  
    private int balance = 1000;  

    public void withDraw(int money) {  
        synchronized (this) {  
            if (canWithDrawByMoney(money)) {  
                try {  
                    String threadName = Thread.currentThread().getName();  
                    System.out.println(threadName + ") 좜금 κΈˆμ•‘ : [" + money + "]");  
                    this.wait(1000);  
                    balance -= money;  
                    System.out.println(threadName + ") balance : [" + balance + "]");  
                } catch (InterruptedException e) {  
                    System.out.println(e.getMessage());  
                    Thread.currentThread().interrupt();  
                }  
            }  
        }  
    }  

    ...
}

πŸ’« Info SonarLint 정적 μ½”λ“œ 뢄석 λ„κ΅¬μ—μ„œλŠ” μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œ λ°©λ²•λ³΄λ‹€λŠ” μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œ μ•ˆμ˜ 동기화 λΈ”λŸ­μ„ ꢌμž₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

μŠ€νƒœν‹± λ©”μ†Œλ“œ μ•ˆμ˜ 동기화 블둝


package thread.obj;  

public class Account {  
    private static int balance = 1000;  

    public static void withDraw(int money) {  
        synchronized (Account.class) {  
            if (canWithDrawByMoney(money)) {  
                try {  
                    String threadName = Thread.currentThread().getName();  
                    System.out.println(threadName + ") 좜금 κΈˆμ•‘ : [" + money + "]");  
                    Thread.sleep(1000);  
                    balance -= money;  
                    System.out.println(threadName + ") balance : [" + balance + "]");  
                } catch (InterruptedException e) {  
                    System.out.println(e.getMessage());  
                    Thread.currentThread().interrupt();  
                }  
            }  
        }  
    }  

    private static boolean canWithDrawByMoney(int money) {  
        return balance >= money;  
    }  

    public boolean canWithDraw() {  
        return balance > 0;  
    }  
}

μœ„μ™€μ˜ μ°¨μ΄λŠ” static 을 μ‚¬μš©ν•˜μ˜€κΈ° λ•Œλ¬Έμ— classλ₯Ό λ„£μ–΄μ•Ό ν•©λ‹ˆλ‹€.

μ„±λŠ₯ 문제

그럼 본둠으둜 λŒμ•„μ™€μ„œ synchronized κ°€ μ„±λŠ₯μ €ν•˜λ₯Ό μΌμœΌν‚€λŠ” μ΄μœ μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

public void withDraw(int money) {  
    synchronized (this) {  
        if (canWithDrawByMoney(money)) {  
            try {  
                String threadName = Thread.currentThread().getName();  
                    System.out.println(threadName + ") 좜금 κΈˆμ•‘ : [" + money + "]");  
                    Thread.sleep(1000);  
                    balance -= money;  
                    System.out.println(threadName + ") balance : [" + balance + "]");  
                    doubleLock();  
                } catch (InterruptedException e) {  
                    System.out.println(e.getMessage());  
                    Thread.currentThread().interrupt();  
            }  
        }  
    }  
}  

private void doubleLock() {  
    synchronized (this) {  
        try {  
            Thread.sleep(1000);  
        } catch (InterruptedException e) {  
            System.out.println(e.getMessage());  
            Thread.currentThread().interrupt();  
        }  
    }  
}

정리

μ‹€μ œλ‘œ μ‹€λ¬΄μ—μ„œλŠ” synchronizedλ₯Ό 많이 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ° 이 방법은 μ„±λŠ₯에 치λͺ…적이기 λ•Œλ¬Έμž…λ‹ˆλ‹€. λ”°λΌμ„œ synchronized μ‚¬μš©μ€ μ§€μ–‘ν•΄μ•Όν•©λ‹ˆλ‹€. λ™μ‹œμ„±μ„ 보μž₯ν•΄μ•Ό ν•˜λŠ” κ²½μš°μ—λŠ” μžλ°”κ°€ μ œκ³΅ν•˜λŠ” thread-safeν•œ 자료ꡬ쑰λ₯Ό μ‚¬μš©ν•΄μ•Όν•©λ‹ˆλ‹€. (ConcurrentHashMap, BlockingQueue λ“±)

JSP 동적 Include?!, 정적 Include?!

JSP의 includeλŠ” λ™μ μœΌλ‘œλ„ν•  수 있고 μ •μ μœΌλ‘œλ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

그러면 각 방식에 λŒ€ν•œ μž₯점과 단점을 μ•Œμ•„λ³΄λ„λ‘ ν•˜κ³  μ–΄λ– ν•œ 방식을 μ‚¬μš©ν•΄μ•Όν•˜λŠ” 지 κ³ λ € 사항을 μž‘μ„±ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

Static Include

JSP νŽ˜μ΄μ§€λ₯Ό μ„œλ²„μ—μ„œ 컴파일 ν•  λ•Œ, include된 λ‚΄μš©μ„ ν•΄λ‹Ή μœ„μΉ˜μ— μ •μ μœΌλ‘œ μ‚½μž…ν•©λ‹ˆλ‹€.

이 방식은 jsp:include λ˜λŠ” <%@ include %> λ””λ ‰ν‹°λΈŒλ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•©λ‹ˆλ‹€.

이 방식에 λŒ€ν•œ μž₯단점은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.2)

  1. μ΄λŠ” μ„œλ²„μ—μ„œ λΆ€ν•˜λ₯Ό 덜 μ£Όμ§€λ§Œ, λͺ¨λ“  νŽ˜μ΄μ§€λ₯Ό λΆˆν•„μš”ν•˜κ²Œ 재 μ»΄νŒŒμΌν•΄μ•Ό ν•  수 있으며, λ™μ μœΌλ‘œ 데이터λ₯Ό μ „λ‹¬ν•˜κΈ° μ–΄λ ΅μŠ΅λ‹ˆλ‹€.
  2. include νŽ˜μ΄μ§€μ— μ„ μ–Έν•œ λ³€μˆ˜λ₯Ό λΆ€λͺ¨νŽ˜μ΄μ§€μ—μ„œ λ³„λ„μ˜ λ³€μˆ˜ 선언없이 μ‚¬μš©μ΄ κ°€λŠ₯ν•˜μ§€λ§Œ λΆ€λͺ¨ νŽ˜μ΄μ§€μ— includeν•œ 파일이 λ§Žμ„κ²½μš° include νŽ˜μ΄μ§€μ—μ„œ μ„ μ–Έλœ λ³€μˆ˜λ₯Ό 좔적해야할 μœ μ§€λ³΄μˆ˜ν•  λ•Œ νž˜λ“­λ‹ˆλ‹€.
  3. JSP νŒŒμΌμ— html이 λ§Žμ•„μ§€κ³  Java λ‘œμ§λ„ λ§Žμ•„μ§€λ©΄ 라인 μˆ˜κ°€ λŠ˜μ–΄λ‚˜κ²Œ λ˜λŠ”λ° 이 λ•Œ λͺ¨λ“  뢀뢄을 μ •μ μœΌλ‘œ ν• λ‹Ήν•˜λ©΄ μ•„λž˜μ™€ 같은 μ—λŸ¬λ‘œκ·Έλ₯Ό λ§Œλ‚  수 μžˆμŠ΅λ‹ˆλ‹€.1) Generated servlet error: The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit 정적 include 방법을 ν™œμš©ν•˜μ—¬ 10,000라인 정도 λ„˜μ–΄κ°€λ©΄ ν•΄λ‹Ή μ—λŸ¬λ₯Ό λ§Œλ‚˜κ²Œ 될 수 μžˆμŠ΅λ‹ˆλ‹€.

Dynamic Include

JSP νŽ˜μ΄μ§€κ°€ 싀행될 λ•Œ, include 된 λ‚΄μš©μ„ λ™μ μœΌλ‘œ μ‹€ν–‰ν•˜κ³  νŽ˜μ΄μ§€μ˜ μ‹€ν–‰ 흐름 쀑에 λ‹€λ₯Έ JSP νŽ˜μ΄μ§€λ₯Ό ν¬ν•¨μ‹œν‚΅λ‹ˆλ‹€. 이 방식은 <jsp:include> λ˜λŠ” Java μ½”λ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬ν˜„ν•©λ‹ˆλ‹€.

이 방식에 λŒ€ν•œ μž₯단점은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.2)

  1. μ΄λŠ” 동적 데이터와 λ³€μˆ˜λ₯Ό κ³΅μœ ν•  수 μžˆμ–΄ μœ μ—°ν•˜κ²Œ μ½˜ν…μΈ λ₯Ό μ‘°ν•©ν•  수 μžˆμ§€λ§Œ, μ„œλ²„μ— λΆ€ν•˜λ₯Ό 더 많이 쀄 수 있으며 응닡 μ‹œκ°„μ— 영ν–₯을 λ―ΈμΉ  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. λΆ€λͺ¨νŽ˜μ΄μ§€μ™€ include νŽ˜μ΄μ§€λŠ” λ³€μˆ˜λ₯Ό κ³΅μœ ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ μœ μ§€ λ³΄μˆ˜μ‹œ νŽΈν•©λ‹ˆλ‹€. ν•˜μ§€λ§Œ λΆ€λͺ¨νŽ˜μ΄μ§€μ—μ„œ includeν•œ νŒŒμΌμ—μ„œ λ³€μˆ˜λ₯Ό μ‚¬μš©μ‹œ <jsp:param name="userName" value="<%=userName%>"/>와 같이 λΆ€λͺ¨νŽ˜μ΄μ§€μ—μ„œ 지정해 μ£Όμ–΄μ•Ό ν•©λ‹ˆλ‹€.

κ³ λ € 사항

  1. λΆ€ν•˜ 관리 동적 includeλŠ” μ„œλ²„ λΆ€ν•˜λ₯Ό μ¦κ°€μ‹œν‚¬ 수 μžˆμœΌλ―€λ‘œ, κΌ­ ν•„μš”ν•œ λΆ€λΆ„μ—λ§Œ 동적 includeλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. 정적 includeλŠ” 일반적으둜 μ„œλ²„ λΆ€ν•˜μ— 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  2. 응닡 μ‹œκ°„ 동적 includeκ°€ 많이 μ‚¬μš©λ  경우, 응닡 μ‹œκ°„μ΄ 느렀질 수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό μ΅œμ†Œν™”ν•˜λ €λ©΄ μ μ ˆν•œ 캐싱 μ „λž΅μ„ κ³ λ €ν•΄μ•Ό ν•©λ‹ˆλ‹€.
  3. λ³€μˆ˜ 곡유 동적 includeλ₯Ό μ‚¬μš©ν•˜λ©΄ λ³€μˆ˜λ₯Ό κ³΅μœ ν•  수 μžˆμœΌλ―€λ‘œ, 예기치 λͺ»ν•œ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ³€μˆ˜λ₯Ό κ³΅μœ ν•  수 μžˆμœΌλ―€λ‘œ, 예기치 λͺ»ν•œ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ³€μˆ˜μ˜ μŠ€μ½”ν”„μ™€ μΆ©λŒμ„ λ°©μ§€ν•˜κΈ° μœ„ν•΄ λ³€μˆ˜λͺ…을 μ‹ μ€‘ν•˜κ²Œ μ„ νƒν•˜κ³ , λ³€μˆ˜ μŠ€μ½”ν”„λ₯Ό μ œμ–΄ν•˜λŠ” 방법을 이해해야 ν•©λ‹ˆλ‹€.
  4. μœ μ—°μ„± 동적 includeλ₯Ό μ‚¬μš©ν•˜λ©΄ 동적 데이터λ₯Ό νŽ˜μ΄μ§€μ— ν¬ν•¨μ‹œν‚¬ 수 μžˆμœΌλ―€λ‘œ, μœ μ—°μ„±μ΄ ν–₯μƒλ©λ‹ˆλ‹€. 이λ₯Ό 톡해 λ™μ μœΌλ‘œ νŽ˜μ΄μ§€λ₯Ό κ΅¬μ„±ν•˜κ³  λ‹€μ–‘ν•œ μ½˜ν…μΈ λ₯Ό 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.

Ref

  1. [JSP] include μ œλŒ€λ‘œ μ•Œκ³  μ“°κΈ° (동적, 정적)
  2. [JSP] 정적, 동적 include
  3. java - synchronized λž€? μ‚¬μš©λ²•?
  4. μžλ°” - Synchronized μŠ€λ ˆλ“œ 동기화 κ°œλ… 및 μ‚¬μš©μ˜ˆμ œ
  5. Java의 Synchronized ν‚€μ›Œλ“œ

μΆ”κ°€μ μœΌλ‘œ κ³΅λΆ€ν•˜λ©΄ 쒋은 λΈ”λ‘œκ·Έ

  1. Java - synchronized 동기화
  2. synchronized와 Moniter
  3. Synchronized ν‚€μ›Œλ“œ