Java Thread

2020. 2. 3. 17:24Β· πŸ’¬ Language/Java

 

1. μŠ€λ ˆλ“œ(Thread)λž€?

- μ–΄λ–€ ν”„λ‘œμ„ΈμŠ€ λ‚΄μ—μ„œ μ‹€ν–‰λ˜λŠ” 흐름(μž‘μ—…)의 λ‹¨μœ„λ‹€.

- ν”„λ‘œμ„ΈμŠ€ λ‚΄ λͺ…λ Ήμ–΄ λΈ”λ‘μœΌλ‘œ μ‹œμž‘, μ’…λ£Œμ μ„ κ°€μ§„λ‹€.

  1. JVM에 μ˜ν•΄ ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€κ°€ λ°œμƒν•˜κ³  main λ‚΄λΆ€μ˜ 싀행문이 ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ‹€.
  2. main() 이외에 λ‹€λ₯Έ μŠ€λ ˆλ“œλ₯Ό λ§Œλ“€λ €λ©΄ Thread 클래슀λ₯Ό μƒμ†ν•˜κ±°λ‚˜ Runnalble μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œλ‹€.
  3. 닀쀑 μŠ€λ ˆλ“œ μž‘μ—… μ‹œ 각 μŠ€λ ˆλ“œλΌλ¦¬ 정보λ₯Ό 주고받을 수 μžˆμ–΄ 처리 κ³Όμ •μ˜ 였λ₯˜λ₯Ό 쀄일 수 μžˆλ‹€.
  4. ν”„λ‘œμ„ΈμŠ€λΌλ¦¬λŠ” 정보λ₯Ό 주고받을 수 μ—†λ‹€.

 

2. λ©€ν‹°μŠ€λ ˆλ”©μ΄λž€?

μ—¬λŸ¬ μŠ€λ ˆλ“œλ₯Ό λ™μ‹œμ— μ‹€ν–‰μ‹œν‚€λŠ” μ‘μš©ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λŠ” 기법이닀.

 

  μž₯점

  • λ©”λͺ¨λ¦¬ 곡유둜 μΈν•œ μ‹œμŠ€ν…œ μžμ› μ†Œλͺ¨κ°€ 쀄어든닀.

  • λ™μ‹œμ— 두 κ°€μ§€ ν™œλ™μ„ ν•˜λŠ” 것이 κ°€λŠ₯ν•΄μ§„λ‹€.

  단점

  • μ„œλ‘œ μžμ›μ„ μ†Œλͺ¨ν•˜λ‹€κ°€ 좩돌이 일어날 κ°€λŠ₯성이 μ‘΄μž¬ν•œλ‹€.

  • μ½”λ“œκ°€ λ‚œν•΄ν•΄μ Έ 버그생성확λ₯ μ΄ λ†’μ•„μ§„λ‹€.

 

3. μŠ€λ ˆλ“œ 생성주기

좜처 : https://promobile.tistory.com/213

New : μΈμŠ€ν„΄μŠ€λŠ” λ§Œλ“€μ–΄μ‘ŒμœΌλ‚˜ 아직 싀행이 λ˜μ§€ μ•Šμ€ μƒνƒœ

Runnable (μ€€λΉ„μƒνƒœ) : start() λ©”μ†Œλ“œ ν˜ΈμΆœμ— μ˜ν•΄ μŠ€λ ˆλ“œλŠ” Runnable μƒνƒœλ‘œ μ΄λ™ν•œλ‹€.

Running (μ‹€ν–‰μƒνƒœ) : μŠ€μΌ€μ€„λŸ¬λŠ” Runnable pool μ²΄ν¬ν•˜κ³  μŠ€λ ˆλ“œλ₯Ό Running μƒνƒœλ‘œ μ΄λ™μ‹œν‚¨λ‹€.

Blocked (μ§€μ—°μƒνƒœ) : sleep(), wait() λ©”μ†Œλ“œ, I/O μž…μΆœλ ₯ μš”μ²­, λŒ€κΈ°μƒνƒœλ‘œ μ΄λ™ν•œλ‹€.

Dead (μ’…λ£Œμƒνƒœ) : 싀행이 μ™„λ£Œλ˜λ©΄ μŠ€λ ˆλ“œλŠ” μ’…λ£Œλ˜κ³  이 μƒνƒœμ—μ„œ λ‹€μ‹œ μ‹œμž‘λ˜λŠ”κ²ƒμ€ λΆˆκ°€λŠ₯ν•˜λ‹€.

 

 

4. synchronized

 

<λ©”μ†Œλ“œλ₯Ό synchronized둜 μ„ μ–Έ>

synchronizedκ°€ λ©”μ†Œλ“œ 선언뢀에 있으면 ν•΄λ‹Ή 객체의 λ©”μ†Œλ“œμ— 2개의 μ“°λ ˆλ“œκ°€ μ ‘κ·Όν•˜λ“ , 100개의 μ“°λ ˆλ“œκ°€ μ ‘κ·Όν•˜λ“  간에 ν•œ μˆœκ°„μ—λŠ” ν•˜λ‚˜μ˜ μ“°λ ˆλ“œλ§Œ 이 λ©”μ†Œλ“œλ₯Ό μˆ˜ν–‰ν•˜κ²Œ λœλ‹€.

  • CommonCalculate 클래슀의 객체λ₯Ό calcλΌλŠ” μ΄λ¦„μœΌλ‘œ 생성
  • ModifyAmountThreadλΌλŠ” 클래슀 객체λ₯Ό 생성할 λ•Œ calcλ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ λ„˜κΈ°κ³  plus() λ©”μ†Œλ“œλ§Œ μˆ˜ν–‰ν•˜λ„λ‘ trueλ₯Ό λ‘λ²ˆμ§Έ λ§€κ°œλ³€μˆ˜λ‘œ λ„˜κΉ€
  • 각각의 μŠ€λ ˆλ“œ μ‹€ν–‰
  • try-catch 블둝 μ•ˆμ—μ„œ join()μ΄λΌλŠ” λ©”μ†Œλ“œλ₯Ό 각각의 μŠ€λ ˆλ“œμ— λŒ€ν•΄ ν˜ΈμΆœν•œλ‹€. [join : μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ  λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦¬λŠ” λ©”μ†Œλ“œ]
  • join()이 λλ‚˜λ©΄ calc 객체의 getAmount() λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•œλ‹€. getAmount() λ©”μ†Œλ“œμ˜ 호좜 κ²°κ³ΌλŠ” join() λ©”μ†Œλ“œ μˆ˜ν–‰ μ΄ν›„μ΄λ―€λ‘œ λͺ¨λ“  μŠ€λ ˆλ“œκ°€ μ’…λ£Œλœ μ΄ν›„μ˜ κ²°κ³Όλ‹€.

<μ•„λž˜ μ½”λ“œμ˜ κ²°κ³Ό μ˜ˆμƒ>

Main 클래슀의 runCommonCalculate() λ©”μ†Œλ“œκ°€ μˆ˜ν–‰λœ ν›„ λ‘κ°œμ˜ μŠ€λ ˆλ“œμ—μ„œ ν•˜λ‚˜μ˜ 객체에 μžˆλŠ” amountλΌλŠ” int νƒ€μž…μ˜ 값에 1을 만번 더해 20000이 좜λ ₯λ˜μ–΄μ•Όν•œλ‹€.

public class Main {
    public static void main(String[] args) {
        Main runSync=new Main();
        for (int i = 0; i < 5; i++)
            runSync.runCommonCalculate();
    }

    public void runCommonCalculate() {
        CommonCalculate calc=new CommonCalculate();
        ModifyAmountThread thread1 = new ModifyAmountThread(calc,true);
        ModifyAmountThread thread2 = new ModifyAmountThread(calc,true);

        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
            System.out.println("Final value is "+calc.getAmount());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class CommonCalculate {
    private int amount;
    public CommonCalculate() {
        amount = 0;
    }
    public void plus(int value) {
        amount += value;
    }
    public void minus(int value) {
        amount -= value;
    }
    public int getAmount() {
        return amount;
    }

}

public class ModifyAmountThread extends Thread {
    private CommonCalculate calc;
    private boolean addFlag;
    public ModifyAmountThread(CommonCalculate calc, boolean addFlag){
        this.calc=calc;
        this.addFlag=addFlag;
    }
    public void run() {
        for (int loop = 0; loop < 10000; loop++) {
            if(addFlag) {
                calc.plus(1);
            } else {
                calc.minus(1);
            }
        }
    }
}

ν•˜μ§€λ§Œ κ²°κ³ΌλŠ” λ‹€μŒκ³Ό 같이 λ‚˜μ˜¨λ‹€.
Final value is 20000

Final value is 17824

Final value is 14589

Final value is 19747

Final value is 20000

 

20000이 λ‚˜μ˜¬λ•Œλ„, λ‚˜μ˜€μ§€ μ•Šμ„λ•Œλ„ μžˆλ‹€.

 

<μ™œ 이런 ν˜„μƒμ΄ μΌμ–΄λ‚˜λŠ”κ°€?>

plus()λ©”μ†Œλ“œλŠ” λ‹€λ₯Έ μ“°λ ˆλ“œμ—μ„œ μž‘μ—…ν•˜κ³  μžˆλ”λΌλ„, μƒˆλ‘œμš΄ μŠ€λ ˆλ“œμ—μ„œ 온 μž‘μ—…λ„ 같이 μ²˜λ¦¬ν•˜κΈ° λ•Œλ¬Έμ— 데이터가 꼬일 수 μžˆλ‹€.

은행창ꡬλ₯Ό μ˜ˆλ‘œλ“€λ©΄ ν•œλͺ…μ˜ 직원이 ν•˜λ‚˜μ˜ μ°½κ΅¬μ—μ„œ ν•œ 고객의 μš”μ²­λ§Œ μ²˜λ¦¬ν•˜λŠ”λ°, λ§Œμ•½ ν•œλ²ˆμ— μ—¬λŸ¬ 고객의 μš”μ²­μ„ μ²˜λ¦¬ν•˜λ©΄ ν•΄λ‹Ή μ°½κ΅¬λŠ” 고객의 μš”μ²­μ΄ λ’€μ£½λ°•μ£½ λ˜μ–΄ ν•œκ±΄λ„ μ œλŒ€λ‘œ 처리 λͺ»ν•˜κ²Œ 될 수 μžˆλ‹€.

 

μ•„λž˜μ²˜λŸΌ synchronizedλ₯Ό plus() λ©”μ†Œλ“œμ— μΆ”κ°€ν•΄μ£Όλ©΄ μ•žμ„  μŠ€λ ˆλ“œμ—μ„œ μˆ˜ν–‰ν•˜κ³ μžˆλŠ” λ©”μ†Œλ“œκ°€ 끝날 λ•Œ κΉŒμ§€ 늦게온 μŠ€λ ˆλ“œλŠ” κΈ°λ‹€λ¦¬κ²Œ λœλ‹€.

  public synchronized void plus(int value) {
  	amount += value;
  }
  public synchronized void minus(int value) {
  	amount -= value;
  }

 

λ©”μ†Œλ“œμ— μΆ”κ°€ν•˜λŠ” 방법이 μ•„λ‹Œ λ‹€μŒκ³Ό 같은 방법도 μ‘΄μž¬ν•œλ‹€.

μ΄λ ‡κ²Œ synchronizedλ₯Ό μΆ”κ°€ν•΄μ£Όλ©΄ λŒ€κΈ°μ‹œκ°„μ„ 효율적으둜 관리할 수 μžˆλ‹€.

    public void plus(int value) {
        synchronized (this) {
            amount += value;
        }
    }
    public void minus(int value) {
        synchronized (this) {
            amount -= value;
        }
    }

 

 

4. 예제

 

1. Single Thread (extends Thread)

import java.util.*;

public class SingleTreadEx extends Thread  {
    private int[] temp;
    public SingleTreadEx(String threadname) {
        super(threadname);
        temp = new int[10];

        for (int start=0; start<temp.length; start++) {
            temp[start]=start;
        }
    }

    public void run() {
        for (int start:temp) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
            System.out.println("Thread Name :"+currentThread().getName());
            System.out.println("temp value :"+start);
        }
    }

    public static void main(String[] args) {
        SingleTreadEx st = new SingleTreadEx("1번 μŠ€λ ˆλ“œ");
        st.start();
    }
}

2. Single Thread (implements Runnable)

public class SingleTreadEx implements Runnable {

    private int[] temp;

    public SingleTreadEx(){
        temp = new int[10];

        for(int start=0;start<temp.length;start++){
            temp[start]=start;
        }
    }

    @Override
    public void run() {
        for(int start:temp){
            try {
                Thread.sleep(1000);

            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }

            System.out.println("Thread Name :"+Thread.currentThread().getName());
            System.out.println("temp value :"+start);
        }
    }

    public static void main(String[] args) {

        SingleTreadEx ct = new SingleTreadEx();
        Thread t = new Thread(ct,"1번 μŠ€λ ˆλ“œ");

        t.start();
    }
}

3. Multi Thread

class ATM implements Runnable {
    private long depositeMoney = 10000;

    public void run() {
        synchronized (this) {

            for (int i = 0; i < 10; i++) {
                notify();
                try {
                    wait();
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (getDepositeMoney() <= 0)
                    break;
                withDraw(1000);
            }
        }
    }

    public void withDraw(long howMuch) {
        if (getDepositeMoney() > 0) {
            depositeMoney -= howMuch;
            System.out.print(Thread.currentThread().getName() + " , ");
            System.out.printf("μž”μ•‘ : %,d 원 %n", getDepositeMoney());
        } else {
            System.out.print(Thread.currentThread().getName() + " , ");
            System.out.println("μž”μ•‘μ΄ λΆ€μ‘±ν•©λ‹ˆλ‹€.");
        }
    }

    public long getDepositeMoney() {
        return depositeMoney;
    }
}


public class SynchronizedEx {
    public static void main(String[] args) {
        ATM atm = new ATM();
        Thread mother = new Thread(atm, "Junho");
        Thread son = new Thread(atm, "Wonbeen");
        mother.start();
        son.start();
    }
}

 

 

*Reference

이상민 / μžλ°”μ˜ μ‹  vol.1 / λ‘œλ“œλΆ / 2013λ…„ 2μ›”

https://coding-factory.tistory.com/279

https://jdm.kr/blog/69

https://raccoonjy.tistory.com/15

'πŸ’¬ Language > Java' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

GSON - com.google.gson.stream.MalformedJsonException  (1) 2022.08.02
Exception Handling  (3) 2020.05.06
Overloadingκ³Ό Overriding  (1) 2020.01.30
Calculator μ‹€μŠ΅ μ™„μ„±  (1) 2020.01.18
StringTokenizer  (0) 2020.01.18
'πŸ’¬ Language/Java' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€
  • GSON - com.google.gson.stream.MalformedJsonException
  • Exception Handling
  • Overloadingκ³Ό Overriding
  • Calculator μ‹€μŠ΅ μ™„μ„±
_μ£Όλ…Έ
_μ£Όλ…Έ
_μ£Όλ…Έ
juno.log
_μ£Όλ…Έ
전체
였늘
μ–΄μ œ
  • λΆ„λ₯˜ 전체보기 (88)
    • πŸ’¬ Language (15)
      • C (1)
      • C++ (1)
      • Java (12)
    • πŸ–₯️ Computer (46)
      • Data Structure (2)
      • Computer Science (3)
      • Algorithm Solution (41)
    • 🌱 Spring (14)
    • πŸ“¦ Database (1)
    • πŸ₯³ Project (6)
      • kakao chatbot (6)
    • πŸ˜† Daily (5)
      • μž‘λ‹΄ (5)
      • TIL (0)

λΈ”λ‘œκ·Έ 메뉴

  • ν™ˆ
  • λΈ”λ‘œκ·Έ 관리
  • GitHub
  • Velog

인기 κΈ€

hELLO Β· Designed By μ •μƒμš°.v4.2.0
_μ£Όλ…Έ
Java Thread
μƒλ‹¨μœΌλ‘œ

ν‹°μŠ€ν† λ¦¬νˆ΄λ°”

κ°œμΈμ •λ³΄

  • ν‹°μŠ€ν† λ¦¬ ν™ˆ
  • 포럼
  • 둜그인

단좕킀

λ‚΄ λΈ”λ‘œκ·Έ

λ‚΄ λΈ”λ‘œκ·Έ - κ΄€λ¦¬μž ν™ˆ μ „ν™˜
Q
Q
μƒˆ κΈ€ μ“°κΈ°
W
W

λΈ”λ‘œκ·Έ κ²Œμ‹œκΈ€

κΈ€ μˆ˜μ • (κΆŒν•œ μžˆλŠ” 경우)
E
E
λŒ“κΈ€ μ˜μ—­μœΌλ‘œ 이동
C
C

λͺ¨λ“  μ˜μ—­

이 νŽ˜μ΄μ§€μ˜ URL 볡사
S
S
맨 μœ„λ‘œ 이동
T
T
ν‹°μŠ€ν† λ¦¬ ν™ˆ 이동
H
H
단좕킀 μ•ˆλ‚΄
Shift + /
⇧ + /

* λ‹¨μΆ•ν‚€λŠ” ν•œκΈ€/영문 λŒ€μ†Œλ¬Έμžλ‘œ 이용 κ°€λŠ₯ν•˜λ©°, ν‹°μŠ€ν† λ¦¬ κΈ°λ³Έ λ„λ©”μΈμ—μ„œλ§Œ λ™μž‘ν•©λ‹ˆλ‹€.