KarelWineProgram1 (KarelOOP2)

Retired DISLab
Swpark (토론 | 기여) 사용자의 2020년 10월 20일 (화) 23:20 버전
(비교) ← 이전 판 | 현재 판 (비교) | 다음 판 → (비교)
이동: 둘러보기, 찾기
/*
 * Copyright 2020 Sangwon Park @ DISLab, HUFS
 * 
 * 생산자, 소비자 프로그램으로서 lock을 이용하지 않고 동작하게 하여
 * 프로그램이 망가지는 예를 보여준다.
 * 가운데 와인을 두고 경쟁하는 예이다.
 * 생산자 2, 소비자 2씩 총 4개의 스레드를 만들어 동작한다.
 * 
 * 프로그램이 망가지원 원인은 다음과 같다.
 * 
 * 1. 와인이 없는데 마시려고 한다. (비퍼가 없는데 pickBeeper 호출)
 * 2. 캐럴이 서로 부딪힌다.
 * 3. 자료구조 붕괴
 * 4. 주위를 돌아다니는 캐럴과 부딪힐 수 있는데 이것은 오류가 아니라 우연이다. 재미로 만든 것이다.
 */
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 Glass {
	transient boolean isFilled = false;
	private int x, y;
 
	public Glass(int x, int y) {
		this.x = x;
		this.y = y;
	}
 
	public Color drink(IKarel karel) {
		IKarelProgram program = IKarelProgram.getProgram();
		Color color = program.getCornerColor(x, y);
		if (color == null)
			throw new ErrorException("와인이 없습니다.");
		program.setCornerColor(x, y, null);
		isFilled = false;
		program.trace();
		return color;
	}
 
	public void fill(IKarel karel, Color color) {
		IKarelProgram program = IKarelProgram.getProgram();
		if (program.getCornerColor(x, y) != null)
			throw new ErrorException("이미 채워져 있습니다.");
		program.setCornerColor(x, y, color);
		isFilled = true;
		program.trace();
	}
}
 
class Consumer extends ColoredKarel {
	private Glass glass;
	private int steps;
 
	public Consumer(String name, Glass glass, int steps) {
		super(name, null);
		this.glass = glass;
		this.steps = steps;
	}
 
	@Override
	public void run() {
		while (true) {
			move(steps);
			if (glass.isFilled)
				glass.drink(this);
			move(steps);
			turnAround();
		}
	}
}
 
class Producer extends ColoredKarel {
	private Glass glass;
	private int steps;
	private Color color;
 
	public Producer(String name, Color color, Glass 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();
		}
	}
}
 
@SuppressWarnings("serial")
public class KarelWineProgram1 extends IKarelProgram {
	Thread[] threads = new Thread[4];
	Glass glass;
 
	@Override
	protected void onInit() {
		int centerX = getWorldWidth() / 2;
		int centerY = getWorldHeight() / 2;
		glass = new Glass(centerX, centerY);
 
		IKarel karel = new Producer("P1", RED, glass, STEP1);
		addIKarel(karel, centerX - 1 - STEP1, centerY, EAST, 1);
		threads[0] = new Thread(karel);
 
		karel = new Consumer("C1", glass, STEP1);
		addIKarel(karel, centerX, centerY - 1 - STEP1, NORTH, 1);
		threads[1] = new Thread(karel);
 
		karel = new Producer("P2", PINK, glass, STEP2);
		addIKarel(karel, centerX + 1 + STEP2, centerY, WEST, 1);
		threads[2] = new Thread(karel);
 
		karel = new Consumer("C2", glass, STEP2);
		addIKarel(karel, centerX, centerY + 1 + STEP2, SOUTH, 1);
		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;
}
개인 도구
이름공간
변수
행위
둘러보기
구성원
연구
연구실
기타
도구모음
인쇄/내보내기