Java를 Java라

제 13 장 - 쓰레드(thread) (2)

noteasy_l.j.s 2022. 3. 28. 22:32

마음을 다시 잡고 시작해보자... 제발...

 

Java의 정석에서는 Thread의 예제로 요리사, 테이블, 고객의 3class를 활용해서 제공한다.

일단 코드 한 번 봅시다.

import java.util.*;

public class Dish {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Table table = new Table();
		new Thread(new Cook(table), "COOK1").start();
		new Thread(new Customer(table, "donut"), "CUST1").start();
		new Thread(new Customer(table, "burger"), "CUST2").start();
	}

}

class Customer implements Runnable{
	private Table table;
	private String food;
	
	Customer(Table table, String food)
	{
		this.table = table;
		this.food = food;
	}
	
	public void run() {
		while (true)
		{
			try {Thread.sleep(10);} catch(InterruptedException e) {}
			String name = Thread.currentThread().getName();
			
			eatFood();
		}
	}
	
	void eatFood() { table.remove(food); }
}

class Table {
	String[] dishNames = { "donut", "donut", "donut", "burger" }; 
	
	private ArrayList dishes = new ArrayList();
	int MAX_FOOD = 10;
	
	public synchronized void add(String dish)
	{
		// 테이블이 가득 찼으면, 음식을 추가 안함.
		while (dishes.size() >= MAX_FOOD) {
			String name = Thread.currentThread().getName();
			System.out.println(name + "is waiting.");
			try {
				wait();
				Thread.sleep(500);
			}
			catch (InterruptedException e) {}
		}
		dishes.add(dish);
		notify(); // 대기중인 CUST 꺠움.
		System.out.println("Dishes:" + dishes.toString());
	}
	
	public synchronized void remove(String dishName)
	{
		String name = Thread.currentThread().getName();
		// 지정된 요리와 일치하는 요리를 테이블에서 제거한다.
		while (dishes.size() == 0) {
			
			System.out.println(name + " is waiting.");
			try {
				Thread.sleep(500);
			} catch(InterruptedException e) {}
		}
		
		while (true)
		{
			for (int i = 0; i < dishes.size(); i++) {
				if (dishName.equals(dishes.get(i))) {
					dishes.remove(i);
					System.out.println(name + " ate a " + dishName);
					notify(); // COOK을 깨움
					return;
				}
			}
			
			try {
				System.out.println(name + " is waiting.");
				add(dishName);
				wait();
				Thread.sleep(500);
			} catch(InterruptedException e) {}
		}		
		
	}
	
	public int dishNum() {
		return dishNames.length;
	}
}

class Cook extends Thread {
	private Table table;	
	
	Cook(Table table)
	{
		this.table = table;		
	}
	public void run()
	{
		while(true)
		{
			int idx = (int)(Math.random() * table.dishNum());
			table.add(table.dishNames[idx]);
			try {Thread.sleep(1);} catch(InterruptedException e) {}
		}
	}
}

Thread 구조

1. Cook이 계속 요리를 한다. 요리할 공간이 부족하면 잔다.(wait())

2. Customer는 계속 먹는다. Table에 먹을 것이 없으면 잔다. (wait())

3. Customer가 요리를 먹으면 자고있는 Cook을 깨운다. (notify())

4. 위의 과정이 계속 반복된다.

 

일단 기본 예제를 다시 한 번 봤는데...

조금은 이해가 되는 것 같다.

그럼 Cook에서 특정 요리를 하게 Customer가 전달 할 수도 있지 않을까?

Customer가 먹을 요리가 없으니, wait()를 하고, Cook을 깨우는데, 깨우면서 요리를 전달하면

Cook은 다른 것이 아니라 요청 받은 요리를 하지 않을까

한 번 찾아봐야겠다

 

일단 이거로 Thread는 끝!!!