KarelWineProgram2 (KarelOOP2)

Retired DISLab
이동: 둘러보기, 찾기
/*
 * Copyright 2020 Sangwon Park @ DISLab, HUFS
 * 
 * 생산자, 소비자 프로그램으로서 lock을 이용하여 경쟁을 잘 쳐러하도록 한다.
 * 가운데 와인(비퍼)를 두고 경쟁하는 구도이다.
 * GoodConsumer는 와인을 마시려고 하고,
 * GoodProducer는 와인을 채우려고 한다.
 * 각 2개씩 총 4개의 스레드를 만들어 동작시킨다.
 * 
 * 동작하는 알고리즘은 GoodGlass에 lock을 거는 것으로 한다.
 * 이때 lock을 걸지 못하는 원하는 상황이 될 때까지 wait(sleep) 한다.
 * wait을 하면 가지고 있던 lock을 푼다. 깨어날 때는 다시 lock을 획득한 상태가 된다.
 * 이때 중요한 점은 깨어났다고 해서 원하는 자원이 반드시 사용가능한 것은 아니라는 것이다.
 * 그러므로 깨어났을 때 검사해야 하는 것은 자원을 사용할 수 있는지 검사하는 것이다.
 * 이것은 프로그램이 sleep 하는 기간이 길어지는 것이 특징이다.
 */
package cp.java.week11.thread;
 
import java.awt.Color;
 
import acm.util.ErrorException;
import hufs.dislab.karel.ColoredKarel;
import hufs.dislab.karel.IKarel;
import hufs.dislab.karel.IKarelProgram;
 
class GoodGlass {
	private transient boolean isFilled = false;
	private int x, y;
 
	public GoodGlass(int x, int y) {
		this.x = x;
		this.y = y;
	}
 
	public synchronized Color drink(IKarel karel) {
		while (!isFilled) {
			try {
		 		this.wait();
			} catch (InterruptedException e) {
			}
		}
		IKarelProgram program = IKarelProgram.getProgram();
		Color color = program.getCornerColor(x, y);
		if (color == null)
			throw new ErrorException("와인이 없습니다.");
		program.setCornerColor(x, y, null);
		isFilled = false;
		this.notifyAll();
		program.trace();
		return color;
	}
 
	public synchronized void fill(IKarel karel, Color color) {
		while (isFilled) {
			try {
				this.wait();
			} catch (InterruptedException e) {
			}
		}
		IKarelProgram program = IKarelProgram.getProgram();
		if (program.getCornerColor(x, y) != null)
			throw new ErrorException("이미 채워져 있습니다.");
		program.setCornerColor(x, y, color);
		isFilled = true;
		this.notifyAll();
		program.trace();
	}
}
 
class GoodConsumer extends ColoredKarel {
	private GoodGlass glass;
	private int steps;
 
	public GoodConsumer(String name, GoodGlass glass, int steps) {
		super(name, null);
		this.glass = glass;
		this.steps = steps;
	}
 
	@Override
	public void run() {
		while (true) {
			move(steps);
			Color color = glass.drink(this); // DRINK
			setColor(color);
			turnAround();
			move(steps);
			setColor(null);
			turnAround();
		}
	}
}
 
class GoodProducer extends ColoredKarel {
	private GoodGlass glass;
	private int steps;
	private Color color;
 
	public GoodProducer(String name, Color color, GoodGlass glass, int steps) {
		super(name, color);
		this.glass = glass;
		this.steps = steps;
		this.color = color;
	}
 
	@Override
	public void run() {
		while (true) {
			move(steps);
			glass.fill(this, color);	// FILL
			setColor(null);
			turnAround();
			move(steps);
			setColor(color);
			turnAround();
		}
	}
}
 
/**
 * 
 * @author Sangwon Park
 * @since KarelOOP 2 (2020.10.1)
 */
@SuppressWarnings("serial")
public class KarelWineProgram2 extends IKarelProgram {
	@Override
	protected void onInit() {
		int centerX = getWorldWidth() / 2;
		int centerY = getWorldHeight() / 2;
		glass = new GoodGlass(centerX, centerY);
 
		IKarel karel = new GoodConsumer("C1", glass, STEP1);
		addIKarel(karel, centerX - 1 - STEP1, centerY, EAST, 0);
		threads[0] = new Thread(karel);
 
		karel = new GoodProducer("P1", RED, glass, STEP1);
		addIKarel(karel, centerX, centerY - 1 - STEP1, NORTH, 0);
		threads[1] = new Thread(karel);
 
		karel = new GoodConsumer("C2", glass, STEP2);
		addIKarel(karel, centerX + 1 + STEP2, centerY, WEST, 0);
		threads[2] = new Thread(karel);
 
		karel = new GoodProducer("P2", PINK, glass, STEP2);
		addIKarel(karel, centerX, centerY + 1 + STEP2, SOUTH, 0);
		threads[3] = new Thread(karel);
	}
 
	@Override
	protected void onStart() {
		for (Thread th : threads)
			th.start();
	}
 
	public static void main(String[] args) {
		IKarelProgram.main(args, null);
	}
 
	private static final int STEP1 = 1;
	private static final int STEP2 = 2;
 
	Thread[] threads = new Thread[4];
	GoodGlass glass;
}
개인 도구
이름공간
변수
행위
둘러보기
구성원
연구
연구실
기타
도구모음
인쇄/내보내기