(一)生产者消费者问题:
1.题目:
采用Java 多线程技术,设计实现一个符合生产者和消费者问题的程序。 对一个对象(枪膛)进行操作,其最大容量是10颗子弹。 生产者线程是一个压入线程,它不断向枪膛中压入子弹;消费者线程是一个射出线程,它不断从枪膛中射出子弹。
2.分析:
这是个生产者与消费者问题,也是线程的同步问题, 为了防止执行个线程访问一个资源时出现忙等待,要使用的wait-notify函数,是两个线程交替执行。
3.解题步骤:
a.创建一个Factory类,包含Produce()方法和Consume()方法;
b.创建一个Producer线程,模拟生产子弹;
c.创建一个Consume线程,模拟消费子弹 ;
d.创建一个测试类Demo.
4.画图理解:
5.扩展 - 线程安全问题
(1)线程安全出现的原因:
a.多线程的环境下;(单线程不会出现安全问题)
b.多个线程拥有资源;
c.对共享资源的操作不是原子性的。(原子性是指一次操作要么执行完,要么不执行)
(2)那么怎么解决线程安全问题呢?
答:使用同步代码块。
格式:
sychronized (对象) {
要同步的代码块(你走我不走,我走你不走)
}
(二)代码体现:
1.创建一个Factory类
public class Factory {
String name;//加工厂名字
int MAX_SIZE;//最多加工子弹数目
int size;//当前剩余子弹数
public Factory(String name, int MAX_SIZE) {
this.name = name;
this.MAX_SIZE = MAX_SIZE;
}
//使用同步方法,保证线程安全
public synchronized void produce(){
while (size >= MAX_SIZE){
try {
//子弹充足,等待消费
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
//加工子弹累了,休息会
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//生产了一颗子弹
size++;
System.out.println("压入了一颗子弹,还剩下" + size + "颗");
//唤醒等待的所有线程
notifyAll();
}
//使用同步方法,保证线程安全
public synchronized void consume(){
while (size <= 0){
try {
//没有子弹了,等待
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(200);//射出子弹累了,休息会
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//射出了一颗子弹
size--;
System.out.println("射出了一颗子弹,还剩下" + size + "颗");
//唤醒等待的所有线程
notifyAll();
}
}
2.创建一个Producer类实现Runnable接口
public class Producer implements Runnable {
Factory factory;
public Producer(Factory factory) {
this.factory = factory;
}
@Override
public void run() {
//循环生产
while (true){
factory.produce();
}
}
}
3.创建一个Consume类实现Runnable接口
public class Consumer implements Runnable{
Factory factory;
public Consumer(Factory factory) {
this.factory = factory;
}
@Override
public void run() {
//循环消费
while (true){
factory.consume();
}
}
}
4.创建一个测试类Demo
public class Demo {
public static void main(String[] args) {
//创建一个加工厂
Factory factory = new Factory("子弹加工厂",200);
//创建一个生产者对象和一个消费者对象
Producer producer = new Producer(factory);
Consumer consumer = new Consumer(factory);
//创建一个生产者线程和一个消费者线程
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
//启动线程
t1.start();
t2.start();
}
}