IT’s Portfolio

[Java] Lecture - Day 16 λ³Έλ¬Έ

Development Study/Java

[Java] Lecture - Day 16

f1r3_r41n 2024. 5. 17. 11:25
728x90
λ°˜μ‘ν˜•

πŸ–₯ Basic Java - Day 16

πŸ‘‰πŸ» [Chapter 12] μžλ°” μŠ€λ ˆλ“œ 기초

λ©€ν‹°νƒœμŠ€ν‚Ή

  • Multi Tasking
    • ν•˜λ‚˜μ˜ μ‘μš© ν”„λ‘œκ·Έλž¨μ΄ μ—¬λŸ¬ 개의 μž‘μ—…(νƒœμŠ€ν¬)을 λ™μ‹œ 처리
  • λ©€ν‹°ν”„λ‘œμ„Έμ‹±(multi-processing)
    • ν•˜λ‚˜μ˜ μ‘μš© ν”„λ‘œκ·Έλž¨μ΄ μ—¬λŸ¬ 개의 ν”„λ‘œμ„ΈμŠ€λ₯Ό μƒμ„±ν•˜κ³ , 각 ν”„λ‘œμ„ΈμŠ€κ°€ ν•˜λ‚˜μ˜ μž‘μ—…μ„ μ²˜λ¦¬ν•˜λŠ” 기법
    • 각 ν”„λ‘œμ„ΈμŠ€λŠ” λ…λ¦½λœ λ©”λͺ¨λ¦¬ μ˜μ—­μ„ λ³΄μœ ν•˜κ³  μ‹€ν–‰
    • ν”„λ‘œμ„ΈμŠ€λ“€κ°„ 톡신(IPC; Inter Process Communication)κ³Ό ν”„λ‘œμ„ΈμŠ€ μ‚¬μ΄μ˜ λ¬Έλ§₯ κ΅ν™˜(Context Switching)에 λ”°λ₯Έ κ³Όλ„ν•œ μ˜€λ²„ν—€λ“œμ™€ μ‹œκ°„ μ†Œλͺ¨μ˜ 문제점
  • λ©€ν‹°μŠ€λ ˆλ”©(multi-threading)
    • ν•˜λ‚˜μ˜ μ‘μš© ν”„λ‘œκ·Έλž¨μ„ λ™μ‹œ μ²˜λ¦¬κ°€ κ°€λŠ₯ν•œ μ—¬λŸ¬ μž‘μ—…μœΌλ‘œ λΆ„ν• 
    • ν•˜λ‚˜μ˜ μ‘μš© ν”„λ‘œκ·Έλž¨μ΄ μ—¬λŸ¬ 개의 μŠ€λ ˆλ“œλ₯Ό μƒμ„±ν•˜μ—¬, 각 μŠ€λ ˆλ“œκ°€ ν•˜λ‚˜μ˜ μž‘μ—…μ„ μ²˜λ¦¬ν•˜λŠ” 기법
    • ν•˜λ‚˜μ˜ μ‘μš© ν”„λ‘œκ·Έλž¨μ— μ†ν•œ μŠ€λ ˆλ“œλ“€μ€ μžμ›κ³Ό λ©”λͺ¨λ¦¬(λ³€μˆ˜, 파일 μ˜€ν”ˆ ν…Œμ΄λΈ” λ“±)λ₯Ό κ³΅μœ ν•˜λ―€λ‘œ, μŠ€λ ˆλ“œκ°„ 톡신과 λ¬Έλ§₯ κ΅ν™˜μ— λ”°λ₯Έ μ˜€λ²„ν—€λ“œκ°€ 적어 빠름

μŠ€λ ˆλ“œ

  • Thread
    • Thread of Control의 쀀말
    • ν”„λ‘œκ·Έλž¨μ„ μ‹€ν–‰ν•˜λŠ” ν•˜λ‚˜μ˜ μ‹€, μ œμ–΄
    • μš΄μ˜μ²΄μ œμ—μ„œ μž‘μ—…μ„ μ‹€ν–‰ν•˜κ³  κ΄€λ¦¬ν•˜λŠ” λ‹¨μœ„
  • ꡬ성
    • μŠ€λ ˆλ“œ μ½”λ“œ
      • μž‘μ—… 싀행을 μœ„ν•΄ μž‘μ„±ν•œ ν”„λ‘œκ·Έλž¨ μ½”λ“œ
      • κ°œλ°œμžκ°€ μž‘μ„±
    • μŠ€λ ˆλ“œ 정보
      • μš΄μ˜μ²΄μ œκ°€ μŠ€λ ˆλ“œμ— λŒ€ν•΄ κ΄€λ¦¬ν•˜λŠ” 정보
      • μŠ€λ ˆλ“œ λͺ…, ID, μ‹€ν–‰ μ†Œμš” μ‹œκ°„, μš°μ„  μˆœμœ„
  • μŠ€λ ˆλ“œμ™€ 운영체제
    • μŠ€λ ˆλ“œλŠ” λ‹€λ₯Έ μŠ€λ ˆλ“œλ₯Ό 생성 및 μ€‘λ‹¨μ‹œν‚€κΈ° μœ„ν•΄ 운영체제λ₯Ό 톡해 이λ₯Ό μˆ˜ν–‰
    • μŠ€λ ˆλ“œλ₯Ό 생성, 쀑단, μ’…λ£Œμ‹œν‚€κ³  μ‹€ν–‰ν•  μŠ€λ ˆλ“œλ₯Ό μŠ€μΌ€μ₯΄λ§ν•˜λŠ” κΆŒν•œμ€ μš΄μ˜μ²΄μ œμ— 있음
  • μžλ°”μ˜ μŠ€λ ˆλ“œ
    • JVM에 μ˜ν•΄ μŠ€μΌ€μ₯΄λ˜λŠ” μ‹€ν–‰ λ‹¨μœ„μ˜ μ½”λ“œ λΈ”λŸ­
    • μŠ€λ ˆλ“œμ˜ 생λͺ… μ£ΌκΈ°(μ‹€ν–‰, 멈좀, μ’…λ£Œ λ“±)λŠ” JVM에 μ˜ν•΄ 관리됨
    • JVM은 μŠ€λ ˆλ“œ λ‹¨μœ„λ‘œ μŠ€μΌ€μ₯΄λ§
  • JVMκ³Ό λ©€ν‹°μŠ€λ ˆλ“œμ˜ 관계
    • ν•˜λ‚˜μ˜ JVM은 ν•˜λ‚˜μ˜ μžλ°” μ‘μš© ν”„λ‘œκ·Έλž¨λ§Œ μ‹€ν–‰
      • μžλ°” μ‘μš© ν”„λ‘œκ·Έλž¨μ΄ μ‹œμž‘λ  λ•Œ JVM이 ν•¨κ»˜ 싀행됨
      • μžλ°” μ‘μš© ν”„λ‘œκ·Έλž¨μ΄ μ’…λ£Œλ˜λ©΄ JVM도 ν•¨κ»˜ μ’…λ£Œλ¨
    • ν•˜λ‚˜μ˜ μ‘μš© ν”„λ‘œκ·Έλž¨μ€ ν•˜λ‚˜ μ΄μƒμ˜ μŠ€λ ˆλ“œλ‘œ ꡬ성 κ°€λŠ₯

μžλ°”μ—μ„œ μŠ€λ ˆλ“œ λ§Œλ“€κΈ°

  • java.lang.Thread 클래슀λ₯Ό 상속받아 μŠ€λ ˆλ“œ μž‘μ„±
  • java.lang.Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜μ—¬ μŠ€λ ˆλ“œ μž‘μ„±
Thread()  // μŠ€λ ˆλ“œ 객체 생성
Thread(Runnable target) // Runnable 객체인 target을 μ΄μš©ν•˜μ—¬ μŠ€λ ˆλ“œ 객체 생성
Thread(String name) // 이름 name인 μŠ€λ ˆλ“œ 객체 생성
Thread(Runnable target, String name)  // Runnable 객체λ₯Ό μ΄μš©ν•˜λ©°, 이름이 name인 μŠ€λ ˆλ“œ 객체 생성
  • Thread 클래슀 μƒμ„±μž
void run()  // μŠ€λ ˆλ“œ μ½”λ“œλ‘œμ„œ JVM에 μ˜ν•΄ 호좜됨. ν•΄λ‹Ή λ©”μ†Œλ“œ μ’…λ£Œ μ‹œ μŠ€λ ˆλ“œλ„ μ’…λ£Œ
void start()  // JVMμ—κ²Œ μŠ€λ ˆλ“œ μ‹€ν–‰ μ‹œμž‘ μš”μ²­
void interrupt()  // μŠ€λ ˆλ“œ κ°•μ œ μ’…λ£Œ
static void yield() // λ‹€λ₯Έ μŠ€λ ˆλ“œμ—κ²Œ μ‹€ν–‰ 양보. JVM은 μŠ€λ ˆλ“œ μŠ€μΌ€μ₯΄λ§μ„ μ‹œν–‰ν•˜λ©° λ‹€λ₯Έ μŠ€λ ˆλ“œ 선택 μ‹€ν–‰
void join() // μŠ€λ ˆλ“œ μ’…λ£Œ μ‹œκΉŒμ§€ κΈ°λ‹€λ¦Ό
long getId()  // μŠ€λ ˆλ“œ ID κ°’ 리턴
String getName()  // μŠ€λ ˆλ“œ 이름 리턴
int getPriority() // μŠ€λ ˆλ“œ μš°μ„ μˆœμœ„ 리턴(1~10)
void setPriority(int n) // μŠ€λ ˆλ“œ μš°μ„ μˆœμœ„ λ³€κ²½
Thread.State getState() // μŠ€λ ˆλ“œ μƒνƒœ 리턴
static void sleep(long mills) // μŠ€λ ˆλ“œ mills μ‹œκ°„ λ™μ•ˆ 정지
static Thread currentThread() // ν˜„μž¬ μ‹€ν–‰ 쀑인 μŠ€λ ˆλ“œ 객체 레퍼런슀 리턴
  • Thread 클래슀 μ£Όμš” λ©”μ†Œλ“œ
import java.awt.*;
import javax.swing.*;

class TimerThread extends Thread {
    private JLabel time;
    public TimerThread(JLabel time) {
        this.time = time;
    }

    @Override
    public void run() {
        int n = 0;
        while(true) {
            time.setText(Integer.toString(n));
            n++;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                return;
            }
        }
    }
}

public class Thread01 extends JFrame {
    Thread01() {
        super("Thread Exam 01");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(300, 200);

        Container c = getContentPane();
        c.setLayout(new FlowLayout());
        JLabel timer = new JLabel();
        timer.setFont(new Font("Gothic", Font.ITALIC, 80));
        c.add(timer);

        TimerThread th = new TimerThread(timer);
        setVisible(true);
        th.start();
    }

    public static void main(String[] args) {
        new Thread01();
    }
}
  • Threadλ₯Ό 상속받아 1초 λ‹¨μœ„μ˜ 타이머 예제
interface Runnable {
    public void run();
}
  • Runnable μΈν„°νŽ˜μ΄μŠ€
import java.awt.*;
import javax.swing.*;

class TimerRunnable implements Runnable {
    private JLabel timer;
    TimerRunnable(JLabel timer) {
        this.timer = timer;
    }

    @Override
    public void run() {
        int n = 0;
        while(true) {
            timer.setText(Integer.toString(n));
            n++;
            try {
                Thread.sleep(1000);
            } catch(InterruptedException e) {
                return;
            }
        }
    }
}

public class Thread02 extends JFrame {
    Thread02() {
        super("Thread Exam 02");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(300, 200);

        Container c = getContentPane();
        JLabel timer = new JLabel();
        c.setLayout(new FlowLayout());
        timer.setFont(new Font("Gothic", Font.ITALIC, 80));
        c.add(timer);

        TimerRunnable tr = new TimerRunnable(timer);
        Thread th = new Thread(tr);
        setVisible(true);

        th.start();
    }

    public static void main(String[] args) {
        new Thread02();
    }
}
  • Runnable μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜μ—¬ 1초 λ‹¨μœ„μ˜ 타이머 예제

μŠ€λ ˆλ“œ 주의 사항

  • run() λ©”μ†Œλ“œ μ’…λ£Œ μ‹œ μŠ€λ ˆλ“œ μ’…λ£Œ
    • μŠ€λ ˆλ“œ 지속을 원할 μ‹œ run() λ©”μ†Œλ“œ λ‚΄μ—μ„œ λ¬΄ν•œλ£¨ν”„ μž‘μ„±
  • ν•œ 번 μ’…λ£Œν•œ μŠ€λ ˆλ“œ λ‹€μ‹œ μ‹œμž‘ λΆˆκ°€λŠ₯
    • λ‹€μ‹œ μŠ€λ ˆλ“œ 객체 생성 ν›„ start() 호좜
  • ν•œ μŠ€λ ˆλ“œμ—μ„œ λ‹€λ₯Έ μŠ€λ ˆλ“œ κ°•μ œ μ’…λ£Œ κ°€λŠ₯

μŠ€λ ˆλ“œ 정보

  • μŠ€λ ˆλ“œ 이름: μŠ€λ ˆλ“œ μ΄λ¦„μœΌλ‘œ μ‚¬μš©μžκ°€ 지정
  • μŠ€λ ˆλ“œ ID: μŠ€λ ˆλ“œ 고유의 μ‹λ³„μž 번호
  • μŠ€λ ˆλ“œ PC(Program Count): ν˜„μž¬ μ‹€ν–‰ 쀑인 μŠ€λ ˆλ“œ μ½”λ“œμ˜ μ£Όμ†Œ
  • μŠ€λ ˆλ“œ μƒνƒœ
    • NEW
      • μŠ€λ ˆλ“œκ°€ μƒμ„±λ˜μ—ˆμ§€λ§Œ μŠ€λ ˆλ“œκ°€ 아직 μ‹€ν–‰ν•  μ€€λΉ„κ°€ λ˜μ§€ μ•Šμ•˜μŒ
    • RUNNABLE
      • μŠ€λ ˆλ“œκ°€ ν˜„μž¬ μ‹€ν–‰λ˜κ³  μžˆκ±°λ‚˜, μ‹€ν–‰ μ€€λΉ„λ˜μ–΄ μŠ€μΌ€μ€„λ§μ„ κΈ°λ‹€λ¦¬λŠ” μƒνƒœ
    • WAITING
      • wait() 호좜 μƒνƒœ
        • λ‹€λ₯Έ μŠ€λ ˆλ“œκ°€ notify()λ‚˜ notifyAll()을 뢈러주기λ₯Ό 기닀리고 μžˆλŠ” μƒνƒœ
      • μŠ€λ ˆλ“œ 동기화λ₯Ό μœ„ν•΄ μ‚¬μš©
    • TIMED_WAITING
      • sleep(n)을 ν˜ΈμΆœν•˜μ—¬ n λ°€λ¦¬μ΄ˆ λ™μ•ˆ μ •μ§€ν•΄μžˆλŠ” μƒνƒœ
    • BLOCK
      • μŠ€λ ˆλ“œκ°€ I/O μž‘μ—…μ„ μš”μ²­ν•˜λ©΄ JVM이 μžλ™μœΌλ‘œ BLOCK μƒνƒœλ‘œ λ§Œλ“¦
    • TERMINATED
      • μŠ€λ ˆλ“œκ°€ μ’…λ£Œν•œ μƒνƒœ
  • μŠ€λ ˆλ“œ μš°μ„ μˆœμœ„: μŠ€λ ˆλ“œ μŠ€μΌ€μ€„λ§ μ‹œ μ‚¬μš©λ˜λŠ” κ°’μœΌλ‘œ 1~10 사이 값이며 10이 μ΅œμƒμœ„ μš°μ„ μˆœμœ„
    • 10(MAX_PRIORITY)
    • 1(MIN_PRIORITY)
    • 5(NORMAL_PRIORITY)
    • main() μŠ€λ ˆλ“œμ˜ μš°μ„ μˆœμœ„λŠ” 초기 5
      • μŠ€λ ˆλ“œλŠ” λΆ€λͺ¨ μŠ€λ ˆλ“œμ™€ 동일 μš°μ„ μˆœμœ„λ₯Ό 가지고 탄생
    • JVM의 μŠ€μΌ€μ₯΄λ§ μ •μ±…
      • μ² μ €ν•œ μš°μ„ μˆœμœ„ 기반
        • κ°€μž₯ 높은 μš°μ„ μˆœμœ„ μŠ€λ ˆλ“œκ°€ μš°μ„ μ  μŠ€μΌ€μ₯΄λ§
        • 동일 μš°μ„ μˆœμœ„ μŠ€λ ˆλ“œλŠ” λŒμ•„κ°€λ©΄μ„œ μŠ€μΌ€μ₯΄λ§(λΌμš΄λ“œ 둜빈)
  • μŠ€λ ˆλ“œ κ·Έλ£Ή: μ—¬λŸ¬ 개의 μžλ°” μŠ€λ ˆλ“œκ°€ ν•˜λ‚˜μ˜ 그룹을 ν˜•μ„±ν•  수 있으며 이 경우 μŠ€λ ˆλ“œκ°€ μ†ν•œ κ·Έλ£Ή
  • μŠ€λ ˆλ“œ λ ˆμ§€μŠ€ν„° μŠ€νƒ: μŠ€λ ˆλ“œκ°€ μ‹€ν–‰λ˜λŠ” λ™μ•ˆ λ ˆμ§€μŠ€ν„°λ“€μ˜ κ°’

main μŠ€λ ˆλ“œ

  • JVM이 μžλ°” μ‘μš© ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ μ‹œμž‘ μ‹œ λ””ν΄νŠΈλ‘œ μƒμ„±λ˜λŠ” μŠ€λ ˆλ“œ
  • JVM은 main μŠ€λ ˆλ“œμ—κ²Œ main() λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰μΌ€ 함
  • main() λ©”μ†Œλ“œκ°€ μ’…λ£Œν•˜λ©΄ main μŠ€λ ˆλ“œ μ’…λ£Œ

μŠ€λ ˆλ“œ μ’…λ£Œμ™€ 타 μŠ€λ ˆλ“œ κ°•μ œ μ’…λ£Œ

public void run() {
    ...
    return;
    ...
}
  • 슀슀둜 μ’…λ£Œ
    • run() μ‹€ν–‰ 도쀑 리턴
    • run()을 μ™„μ „νžˆ μ‹€ν–‰ν•˜μ—¬ μ’…λ£Œ
B.interrupt()
  • κ°•μ œ μ’…λ£Œ
    • ν•œ μŠ€λ ˆλ“œκ°€ λ‹€λ₯Έ μŠ€λ ˆλ“œλ₯Ό κ°•μ œ μ’…λ£Œ
    • μ’…λ£Œν•˜κ³ μž ν•˜λŠ” μŠ€λ ˆλ“œμ˜ interrupt() λ©”μ†Œλ“œ 호좜
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.*;

public class Thread03 extends JFrame implements Runnable {
    private Thread th;
    Thread03() {
        super("Thread Exam 03");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(300, 200);
        setLocation(300, 300);

        getContentPane().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if(!th.isAlive()) return;
                th.interrupt();
            }
        });
        setVisible(true);

        th = new Thread(this);
        th.start();
    }

    @Override
    public void run() {
        Random r = new Random();
        while(true) {
            try {
                Thread.sleep(20);
            } catch(InterruptedException e) {
                return;
            }
            int x = getX()+r.nextInt()%5;
            int y = getY()+r.nextInt()%5;
            setLocation(x, y);
        }
    }

    public static void main(String[] args) {
        new Thread03();
    }
}
  • μ§„λ™ν•˜λŠ” μŠ€λ ˆλ“œμ™€ μŠ€λ ˆλ“œ κ°•μ œ μ’…λ£Œ 예제

μŠ€λ ˆλ“œμ˜ μ‹œμž‘κ³Ό μ’…λ£Œ

  • λ©€ν‹°μŠ€λ ˆλ“œλ₯Ό 가진 ν”„λ‘œκ·Έλž¨μ€ λ‹€μˆ˜ 개의 μ‹€ν–‰ 흐름을 가짐
    • start()에 μ˜ν•΄ 닀쀑 흐름 μ‹œμž‘
    • λ‹€μˆ˜ 개의 μ‹€ν–‰ 흐름을 λ‹€μ‹œ ν•˜λ‚˜μ˜ νλ¦„μœΌλ‘œ ν†΅ν•©ν•˜κΈ° μœ„ν•΄μ„œ μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ˜λŠ” μ‹œμ μ—μ„œ join() μ‚¬μš©
      • InterruptedException 처리 μš”ν•¨

μŠ€λ ˆλ“œ 동기화

  • Thread Synchronization
    • λ©€ν‹°μŠ€λ ˆλ“œ ν”„λ‘œκ·Έλž¨ μž‘μ„± μ‹œ 주의점
      • λ‹€μˆ˜μ˜ μŠ€λ ˆλ“œκ°€ 곡유 데이터에 λ™μ‹œ μ ‘κ·Όν•˜λŠ” 경우, 곡유 λ°μ΄ν„°μ˜ 값에 μ˜ˆμƒμΉ˜ λͺ»ν•œ κ²°κ³Όκ°€ λ°œμƒν•  수 있음
    • μŠ€λ ˆλ“œ μ‚¬μ΄μ˜ μ‹€ν–‰μˆœμ„œ μ œμ–΄, 곡유 데이터에 λŒ€ν•œ 접근을 μ›ν™œν•˜κ²Œ ν•˜λŠ” 기법
    • 동기화 핡심: μŠ€λ ˆλ“œμ˜ 곡유 데이터에 λŒ€ν•œ 배타적 독점 μ ‘κ·Ό 보μž₯
    • λ©€ν‹°μŠ€λ ˆλ“œμ˜ 곡유 데이터 λ™μ‹œ μ ‘κ·Ό 문제 ν•΄κ²°μ±…
      • 곡유 데이터λ₯Ό μ ‘κ·Όν•˜λŠ” λͺ¨λ“  μŠ€λ ˆλ“œμ˜ ν•œ 쀄 μ„Έμš°κΈ°
      • ν•œ μŠ€λ ˆλ“œκ°€ 곡유 데이터에 λŒ€ν•œ μž‘μ—…μ„ 끝낼 λ•ŒκΉŒμ§€ λ‹€λ₯Έ μŠ€λ ˆλ“œκ°€ λŒ€κΈ°ν•˜λ„λ‘ 함
    • μžλ°”μ—μ„œ μŠ€λ ˆλ“œ 동기화λ₯Ό μœ„ν•œ 방법
      • synchronized ν‚€μ›Œλ“œλ‘œ 동기화 블둝 지정
      • wait()-notify() λ©”μ†Œλ“œλ‘œ μŠ€λ ˆλ“œ μ‹€ν–‰ μˆœμ„œ μ œμ–΄

synchronized 블둝 지정

  • synchronized ν‚€μ›Œλ“œ
    • ν•œ μŠ€λ ˆλ“œκ°€ λ…μ ν•΄μ„œ μ‹€ν–‰ν•΄μ•Ό ν•˜λŠ” λΆ€λΆ„(동기화 μ½”λ“œ)을 ν‘œμ‹œν•˜λŠ” ν‚€μ›Œλ“œ
      • μž„κ³„ μ˜μ—­(critical section) ν‘œκΈ° ν‚€μ›Œλ“œ
    • λ©”μ†Œλ“œ 전체 ν˜Ήμ€ μ½”λ“œ 블둝을 synchronized λΈ”λ‘μœΌλ‘œ 지정
  • synchronized 블둝에 λŒ€ν•œ 컴파일러의 처리
    • 블둝 μ§„μž… μ‹œ 락이 걸리고(lock), λΈ”λ‘μ—μ„œ λΉ μ Έλ‚˜μ˜¬ μ‹œ 락이 ν’€λ¦Ό(unlock)
public class Thread04 {
    static SharedPrinter p = new SharedPrinter();   // 곡유 데이터 생성
    private static String [] engText = { "Wise men say, ",
            "only fools rush in",
            "But I can't help, ",
            "falling in love with you",
            "Shall I stay? ",
            "Would it be a sin?",
            "If I can't help, ",
            "falling in love with you" };
    private static String [] korText = { "동해물과 백두산이 마λ₯΄κ³  닳도둝, ",
            "ν•˜λŠλ‹˜μ΄ λ³΄μš°ν•˜μ‚¬ 우리 λ‚˜λΌ λ§Œμ„Έ",
            "무ꢁ화 μ‚Όμ²œλ¦¬ ν™”λ €κ°•μ‚°, ",
            "λŒ€ν•œ μ‚¬λžŒ λŒ€ν•œμœΌλ‘œ 길이 λ³΄μ „ν•˜μ„Έ",
            "남산 μœ„μ— μ € μ†Œλ‚˜λ¬΄, 철갑을 두λ₯Έ λ“―",
            "λ°”λžŒμ„œλ¦¬ λΆˆλ³€ν•¨μ€ 우리 기상일세.",
            "무ꢁ화 μ‚Όμ²œλ¦¬ ν™”λ €κ°•μ‚°, ",
            "λŒ€ν•œ μ‚¬λžŒ λŒ€ν•œμœΌλ‘œ 길이 λ³΄μ „ν•˜μ„Έ" };

    public static void main(String[] args) {
        Thread th1 = new WorkerThread(p, engText);
        Thread th2 = new WorkerThread(p, korText);
        th1.start();
        th2.start();
    }
}

class SharedPrinter {   // WorkerThread에 μ˜ν•΄ λ™μ‹œ μ ‘κ·Όλ˜λŠ” 클래슀
    synchronized void print(String text) {  // synchronized μƒλž΅ μ‹œ ν•œκΈ€κ³Ό μ˜μ–΄κ°€ ν•œ 쀄에 μ„žμ—¬ 좜λ ₯λ˜λŠ” 경우 λ°œμƒ
        for(int i=0; i<text.length(); i++)
            System.out.print(text.charAt(i));
        System.out.println();
    }
}

class WorkerThread extends Thread { // μŠ€λ ˆλ“œ 클래슀
    private SharedPrinter p;
    private String[] text;

    WorkerThread(SharedPrinter p, String[] text) {
        this.p = p; this.text = text;
    }
    @Override
    public void run() {
        for(int i=0;i<text.length; i++)
            p.print(text[i]);
    }
}
  • sychronized 블둝 예제

wait()-notify()

  • producer-consumer 문제
    • 곡유 λ©”λͺ¨λ¦¬λ₯Ό 톡해 두 개 μ΄μƒμ˜ μŠ€λ ˆλ“œκ°€ 데이터λ₯Ό μ£Όκ³  받을 λ•Œ, μŠ€λ ˆλ“œλ“€μ΄ 곡유 λ©”λͺ¨λ¦¬λ₯Ό λ™μ‹œ μ ‘κ·Όν•˜λŠ” 문제
  • producer-consumer 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•œ μŠ€λ ˆλ“œ 동기화 λ©”μ†Œλ“œ
    • Object의 λ©”μ†Œλ“œ, synchronized 블둝 λ‚΄μ—μ„œλ§Œ μ‚¬μš©λ˜μ–΄μ•Ό 함
    • wait(): λ‹€λ₯Έ μŠ€λ ˆλ“œκ°€ notify()λ₯Ό ν˜ΈμΆœν•  λ•ŒκΉŒμ§€ λŒ€κΈ°
    • notify(): λŒ€κΈ°ν•˜κ³  μžˆλŠ” μŠ€λ ˆλ“œλ₯Ό κΉ¨μ›Œ RUNNABLE μƒνƒœλ‘œ λ§Œλ“¦
    • notifyAll(): λŒ€κΈ°ν•˜κ³  μžˆλŠ” λͺ¨λ“  μŠ€λ ˆλ“œλ₯Ό 깨우고 λͺ¨λ‘ RUNNABLE μƒνƒœλ‘œ λ§Œλ“¦
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class MyLabel extends JLabel {
    int barSize = 0;
    int maxBarSize;

    MyLabel(int maxBarSize) {
        this.maxBarSize = maxBarSize;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.MAGENTA);
        int width =
                (int)((double)getWidth()*barSize/maxBarSize);
        if(width==0) return;
        g.fillRect(0, 0, width, this.getHeight());
    }

    synchronized void fill() {
        if(barSize==maxBarSize) {
            try {
                wait();
            } catch(InterruptedException e) { return; }
        }
        barSize++;
        repaint();
        notify();
    }

    synchronized void consume() {
        if(barSize==0) {
            try {
                wait();
            } catch(InterruptedException e) { return; }
        }
        barSize--;
        repaint();
        notify();
    }
}

class ConsumerThread extends Thread {
    MyLabel bar;
    ConsumerThread(MyLabel bar) {
        this.bar = bar;
    }

    @Override
    public void run() {
        while(true) {
            try {
                sleep(200);
                bar.consume();
            } catch(InterruptedException e) { return; }
        }
    }
}

public class Thread05 extends JFrame {
    private MyLabel bar = new MyLabel(100);

    Thread05() {
        super("Thread Exam 05");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(350, 200);

        Container c = getContentPane();
        c.setLayout(null);
        bar.setBackground(Color.ORANGE);
        bar.setOpaque(true);
        bar.setLocation(20, 50);
        bar.setSize(300, 20);
        c.add(bar);
        c.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                bar.fill();
            }
        });
        setVisible(true);

        c.setFocusable(true);
        c.requestFocus();
        ConsumerThread ct = new ConsumerThread(bar);
        ct.start();
    }

    public static void main(String[] args) {
        new Thread05();
    }
}
  • wait()-notify() 예제
728x90
λ°˜μ‘ν˜•

'Development Study > Java' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[Java] Lecture - Day 18  (1) 2024.06.06
[Java] Lecture - Day 17  (1) 2024.06.06
[Java] Lecture - Day 15  (0) 2024.04.26
[Java] Lecture - Day 14  (0) 2024.04.05
[Java] Lecture - Day 13  (1) 2024.03.30
Comments