采用Java 多线程技术,设计实现一个符合生产者和消费者问题的程序。对一个对象(枪膛)进行操作,
其最大容量是12颗子弹。生产者线程是一个压入线程,它不断向枪膛中压入子弹;消费者线程是一个射出线程,
它不断从枪膛中射出子弹。
要求:
(1)给出分析过程说明。
(2)程序输出,要模拟体现对枪膛的压入和射出操作;
(3)设计程序时应考虑到两个线程的同步问题。
这是一道典型的生产者消费这问题,同时可以用BlockingQueue得到很好的实现。
创建一个Gun的类,其拥有Bullet,Shooter,BulletProductor三个内部类。
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
模拟结束
停止射击
停止装子弹