KarelWineProgram1 (KarelOOP2)
Retired DISLab
/* * 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; }