Algorithm Study/Java

프로세스와 쓰레드 (by 얄코)

728x90
반응형

 

용어 설명

프로그램 : 🏪 식당 → 배를 채우는 서비스 제공

  • 윈도우에서 .exe라는 이름이 붙은 파일

프로세스 : 👨🏻‍🍳 요리사 → 조리하는 기능

  • 프로그램이 실행되서 돌아가고 있는 상태
  • 컴퓨터가 일을 하고 있는 상태
  • 운영체제가 여러개의 프로세스를 돌리기 때문에 컴퓨터로 멀티태스킹이 가능
    • 동시적(Concurrentcy), 병렬적(Parallelism) 작업의 혼합으로 이루어짐
  • 컴퓨터의 자원을 분할해서 사용 → 하나의 프로세스는 다른 프로세스에 접근하지 못함

쓰레드 : 🍜 조리 공간 → 조리를 위한 작업

  • 한 프로세스 내부에서 여러 갈래의 작업이 이루어짐
  • 프로세스에서 주어지는 자원을 모든 쓰레드가 공유
  • cf. 속도와 효율면에서 장점, 프로세스 안에서 공유되는 변수에 여러 쓰레드가 동시에 접근 → 원하는대로 작업되지 않을 수 있음

 

코드

package org.example;
import java.util.Scanner;

public class RamenProgram {

    public static void main(String[] args) {
        int num;
        Scanner input = new Scanner(System.in);
        System.out.println("라면 몇 개 끓일까요?");

        num = input.nextInt();
        System.out.println(num + "개 주문 완료! 조리시작!");
        try {
            RamenCook ramenCook = new RamenCook(num);
            // 4개의 쓰레드를 만들어서 진행
            new Thread(ramenCook,"A").start();
            new Thread(ramenCook,"B").start();
            new Thread(ramenCook,"C").start();
            new Thread(ramenCook,"D").start();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

interface Runnable {
    public void run();
}

class currentThread extends Thread {
    public RamenCook ramenCook;
    static String name;

    currentThread() {
        this(new RamenCook(5) , "");
    }

    currentThread(RamenCook ramenCook , String nam) {
        this.ramenCook = ramenCook;
        this.name = name;
    }
}

class RamenCook extends Thread implements Runnable {
    private int ramenCount;
    private String[] burners = {"_","_","_","_"};

    public RamenCook(int count) {
        ramenCount = count;
    }

    // 라면 끓이기 진행 
    @Override
    public void run() {
        while(ramenCount > 0) {
						
            // 하나의 라면 끓이기
            	synchronized(this) {  // 여러 쓰레드가 동시에 작동하지 않도록 방지
                ramenCount--;
                System.out.println(Thread.currentThread().getName() + " : " + ramenCount + "개 남았습니다");
            }

            // 비어있는 버너를 찾아 사용
            for(int i = 0; i < burners.length; i++) {
                if(!burners[i].equals("_")) {
                    continue;
                }

                synchronized(this) {
                //if(burners[i].equals("_"))
                //{
                burners[i] = Thread.currentThread().getName();
                System.out.println("     " + Thread.currentThread().getName() + " : [" + (i + 1) + "]번 버너 ON");
                showBurners();  // 버너의 상태 확인
                //}
                }

                try {
                    Thread.sleep(2000);
                } catch(Exception e) {
                    e.printStackTrace();
                }

                	synchronized(this) {
                    burners[i] = "_";
                    System.out.println("     " + Thread.currentThread().getName() + " : [" + (i + 1) + "]번 버너 OFF" );
                    showBurners();
                }

                break;
            }

            // 각 쓰레드가 랜덤 시간동안 정지 될 수 있도록 함 -> 쓰레드 실행의 순서가 않고 섞이도록 함
            try {
                Thread.sleep(Math.round(1000 * Math.random()));
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 버너의 상태 확인
    private void showBurners() {
        String stringToPrint = "                                                             ";
        for(int i = 0; i < burners.length; i++) {
            stringToPrint += (" " + burners[i]);
        }
        System.out.println(stringToPrint);
    }
}

 

실행 결과 창