(一)生产者消费者问题:
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(); } }