生産消費者のシミュレーション


Javaマルチスレッド技術を採用し、生産者と消費者の問題に合致するプログラムを設計して実現する.1つの対象(銃口)を操作し、その最大容量は12個の弾丸である.生産者スレッドは1つの圧入スレッドであり、銃口に絶えず弾丸を圧入する.消費者スレッドは1つの射出スレッドであり、銃口から絶えず弾丸を射出する.要求:(1)分析過程の説明を与える.(2)プログラム出力は、銃口に対する圧入と射出操作をシミュレートする.(3)プログラムを設計する際には,2つのスレッドの同期問題を考慮すべきである.
これは典型的な生産者消費という問題であり、同時にBlockingQueueでよく実現することができる.
Bullet,Shooter,BulletProductorの3つの内部クラスを持つGunクラスを作成します.
BulletProductorは弾丸の生産を担当し、弾丸の個数が12より大きい者は生産しない.
Shooterは射撃を担当し、弾丸を消費する.
具体的なコードは以下の通りです.
package exam.b;

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 4、	  Java      ,                    。     (  )    ,
 *       12   。            ,           ;            ,
 *            。
 * 	  :
 * 	(1)        。
 * 	(2)    ,                ;
 * (2)                  。

 * @author  e
 *
 * 2010-5-27   07:39:26
 */
public class Gun {
	class Bullet{
		int id = bulletCounter++;
		@Override
		public String toString() {
			// TODO Auto-generated method stub
			return "" + id;
		}
	}
	class Shooter implements Runnable{
		BlockingQueue<Bullet> bullets;
		Random r = new Random();
		Shooter(BlockingQueue<Bullet> bullets){
			this.bullets = bullets;
		}
		void shoot() throws InterruptedException{
			Bullet bullet = bullets.take();
			System.out.println("    :" + bullet + "---      :" + bullets.size());
		}
		@Override
		public void run() {
			try {
				while(!Thread.interrupted()){
					shoot();
					TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				System.out.println("    ");
			}
			
		}
		
	}
	class BulletProductor implements Runnable{
		BlockingQueue<Bullet> bullets;
		Random r = new Random();
		public BulletProductor(BlockingQueue<Bullet> bullets) {
			this.bullets = bullets;
		}
		public void product(){
			if(bullets.size() < BULLET_SIZE){//    
				Bullet bullet = new Bullet();
				bullets.add(bullet);
				System.out.println("    :" + bullet + "---      :" + bullets.size());
			}
		}
		@Override
		public void run() {
			try {
				while(!Thread.interrupted()){
					product();
					TimeUnit.MILLISECONDS.sleep(r.nextInt(500));
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				System.out.println("     ");
			}
		}
		
	}
	static int bulletCounter = 0;
	static final int BULLET_SIZE = 12;
	BlockingQueue<Bullet> bullets;
	ExecutorService exec;
	Gun(ExecutorService exec){
		this.bullets = new LinkedBlockingQueue<Bullet>();
		this.exec = exec;
	}
	public void action(){
		exec.execute(new BulletProductor(bullets));
		exec.execute(new Shooter(bullets));
	}
	public static void main(String[] args) throws InterruptedException {
		ExecutorService exec = Executors.newCachedThreadPool();
		Gun gun = new Gun(exec);
		gun.action();
		TimeUnit.SECONDS.sleep(6);
		exec.shutdownNow();
		System.out.println("    ");
	}
}

 
outPut:
射出弾:0---銃弾数:0装填弾:0---銃弾数:0装填弾:1---銃弾数:1装填弾:2---銃弾数:2装填弾:3---銃弾数:3射出弾:1---銃弾数:2装填子弾:4---銃弾数:3装填弾:5---銃弾数:4射出弾:2---銃弾数3装填弾:6---銃弾数:4装填弾:7---銃弾数:5射出弾:3---銃弾数:4装填弾:8---銃弾数:5装填弾:9---銃弾数:6射出弾:4---銃弾数:5装填弾:10---銃弾数:6装填弾:11---銃弾数:7射出弾:5---銃弾数数:6装填弾:12---銃口弾数:7装填弾:13---銃口弾数:8装填弾:14---銃口弾数:9射出弾:6---銃口弾数:8射出弾:7---銃口弾数:7装填弾:15---銃口弾数量:8射出弾:8---銃口弾数:7装填弾:16---銃口弾数:8装填弾:17---銃口弾数銃弾数:9装填弾:18---銃弾数:10射出弾:9---銃弾数:9装填弾:19---銃弾数:10射出弾:10---銃弾数:9装填弾:20---銃弾数:10装填弾:21---銃弾数:11装填弾:22---銃弾数:12射出弾:11---銃弾数:11シミュレーション射撃停止装弾停止