シミュレーション[自動車製造]
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は複数のスレッドで使用される可能性があります.そのため、明らかな方法でスレッドを安全にする必要があります.