シミュレーション[自動車製造]

7833 ワード

class Car{
	private final int id;
	private boolean 
		engine = false,
		driveTrain = false,
		wheels = false;
	
	public Car(int idn){
		id = idn;
	}
	public Car(){
		id = -1;
	}
	public synchronized int getId(){
		return id;
	}
	public synchronized void addEngine(){
		engine = true;
	}
	public synchronized void addDriveTrain(){
		driveTrain = true;
	}
	public synchronized void addWheels(){
		wheels = true;
	}
	public synchronized String toString(){
		return "Car " +id +"[ engine: " + engine
			+ " driveTrain: " + driveTrain + " wheels: "+ wheels+ " ]";
	}
}

class CarQueue extends LinkedBlockingQueue<Car>{}

class ChassisBuilder implements Runnable{
	private CarQueue carQueue;
	private int counter = 0;
	public ChassisBuilder(CarQueue cq){
		carQueue =cq;
	}
	public void run(){
		try {
			while(!Thread.interrupted()){
				TimeUnit.MILLISECONDS.sleep(500);
				Car c = new Car(counter++);
				System.out.println("ChassisBuilder created " +c);
				// Insert into queue
				carQueue.put(c);
			}
		} catch (InterruptedException e) {
			System.out.println("Interrupted: ChassisBuilder");
		}
		System.out.println("ChassisBuilder off");
	}
}

class Assembler implements Runnable{
	private CarQueue chassisQueue, finishingQueue;
	private Car car;
	private CyclicBarrier barrier = new CyclicBarrier(4);
	private RobotPool robotPool;
	public Assembler(CarQueue cq, CarQueue fq, RobotPool rp){
		chassisQueue = cq;
		finishingQueue = fq;
		robotPool = rp;
	}
	public Car car(){
		return car;
	}
	public CyclicBarrier barrier(){
		return barrier;
	}
	public void run(){
		try {
			while(!Thread.interrupted()){
				// Blocks until chassis is available;
				car = chassisQueue.take();
				// Hire robots to perform work;
				robotPool.hire(EngineRobot.class, this);
				robotPool.hire(DriveTrainRobot.class, this);
				robotPool.hire(WheelRobot.class, this);
				barrier.await();	// Unitl the robots finish
				// Put car into finishedQueue for futher work
				finishingQueue.put(car);
			}
		} catch (InterruptedException e) {
			System.out.println("Exiting Assembler via interrupt");
		} catch (BrokenBarrierException e) {
			// This one we want to know about
			throw new RuntimeException(e);
		}
		System.out.println("Assembler off");
	}
}

class Reporter implements Runnable{
	private CarQueue carQueue;
	public Reporter(CarQueue cq){
		carQueue = cq;
	}
	public void run(){
		try {
			while(!Thread.interrupted()){
				System.out.println(carQueue.take());
				System.out.println();
			}
		} catch (InterruptedException e) {
			System.out.println("Exiting Reporter via interrupt");
		}
		System.out.println("Reporter off");
	}
}

abstract class Robot implements Runnable{
	private RobotPool pool;
	public Robot(RobotPool p){
		pool = p;
	}
	protected Assembler assembler;
	public Robot assignAssembler(Assembler assembler){
		this.assembler = assembler;
		return this;
	}
	private boolean engage = false;
	public synchronized void engage(){
		engage = true;
		notifyAll();
	}
	// The part of run() that's different for each robot;
	abstract protected void performService();
	public void run(){
		try {
			powerDown();	// Wait unitll needed
			while(!Thread.interrupted()){
				performService();
				assembler.barrier().await();	// Synchronized
				// We're done with that job...
				powerDown();
			}
		} catch (InterruptedException e) {
			System.out.println("Exiting "+ this+ " via interrupt");
		} catch (BrokenBarrierException e) {
			// This one we want to know about
			throw new RuntimeException(e);
		}
		System.out.println(this +" off");
	}
	private synchronized void powerDown() throws InterruptedException{
		engage = false;
		assembler = null; // Disconnet from the Assembler;
		// Put ourserlves back in the available pool;
		pool.release(this);
		while(engage == false)	// Power down
			wait();
	}
	@Override
	public String toString() {
		return getClass().getName();
	}
}

class EngineRobot extends Robot{
	public EngineRobot(RobotPool pool){
		super(pool);
	}
	protected void performService(){
		System.out.println(this +" installing engine");
		assembler.car().addEngine();
	}
}

class DriveTrainRobot extends Robot{
	public DriveTrainRobot(RobotPool pool){
		super(pool);
	}
	protected void performService(){
		System.out.println(this+" installing DriveTrain");
		assembler.car().addDriveTrain();
	}
}

class WheelRobot extends Robot{
	public WheelRobot(RobotPool pool){
		super(pool);
	}
	protected void performService(){
		System.out.println(this + " installing Wheels");
		assembler.car().addWheels();
	}
}

class RobotPool{
	// Quietly prevents identical entries;
	private Set<Robot> pool = new HashSet<Robot>();
	public synchronized void add(Robot r){
		pool.add(r);
		notifyAll();
	}
	public synchronized void hire(Class<? extends Robot> robotType, 
			Assembler d) throws InterruptedException{
		for(Robot r : pool)
			if(r.getClass().equals(robotType)){
				pool.remove(r);
				r.assignAssembler(d);
				r.engage();	// Power it up to do the task
				return;
			}
		wait();	// None available
		hire(robotType, d);	// Try again, recursively
	}
	public synchronized void release(Robot r){
		add(r);
	}
}

public class CarBuilder {
	public static void main(String[] args) throws InterruptedException {
		CarQueue chassisQueue = new CarQueue(),
			finishingQueue = new CarQueue();
		ExecutorService exec = Executors.newCachedThreadPool();
		RobotPool robotPool = new RobotPool();
		exec.execute(new EngineRobot(robotPool));
		exec.execute(new DriveTrainRobot(robotPool));
		exec.execute(new WheelRobot(robotPool));
		exec.execute(new Assembler(chassisQueue, finishingQueue, robotPool));
		exec.execute(new Reporter(finishingQueue));
		// Start everything running by producing chassis;
		exec.execute(new ChassisBuilder(chassisQueue));
		TimeUnit.SECONDS.sleep(7);
		exec.shutdownNow();
	}
}

 
CarはCarQueueを介してある場所から別の場所に転送され、CarQueueはLinkedBlockingQueueタイプです.ChassisBuilderは修飾されていないCarを作成し、CarQueueに配置しました.AssemblerはCarQueueからCarを取り出し、Robotを雇って加工した.CyclicBarrierはAssemblerを待機させます.すべてのRobotが完了するまで、その時点でCarをCarQueueから離れるまで配置し、次の操作に転送します.最も包括的なCarQueueの消費者はReportオブジェクトであり、Carのみを印刷して、すべてのタスクが正しく完了したことを示します.Carはそのすべての方法をsynchronizedに設定した.それが示すように、この例では、Carは工事の内部で列を通じて動いており、いつでも1つのタスクだけがある車で働くことができるため、これは余計です.基本的に、キューはCarに強制的にシリアル化されてアクセスすることができる.しかし、これはあなたが落ちる可能性のある罠です.「Carクラスを同期させないことで最適化してみましょう.Carはここで同期する必要がないように見えます.しかし、このシステムが別のCarが同期する必要があるシステムに接続されると、破壊されます.//つまり、Carは複数のスレッドで使用される可能性があります.そのため、明らかな方法でスレッドを安全にする必要があります.