问题意义
生产者消费者问题是一个很经典的问题,通过解决此问题,能够学到多线程的的知识。
程序设计思路
在本程序中采用信号灯的方式,用Flag作为标志位,指示生产过程和消费过程是否结束。Flag为true时,生产者开始生产,消费者等待,Flag为false时,消费者开始消费,生产者等待。使用synchronize来锁定生产过程和消费过程,使得两个线程调用一个资源的时候能够有序进行。
程序清单
完整的程序有四个类文件组成,分别是Movie.java,Player.java, Watcher.java ,App.java。
Movie.java文件中源程序如下:
[java] view plain copy
package com.bjsxt.thread.pro;
/**
* 一个场景,共同的资源
* 生产者消费者模式,信号灯法
* wait等待,它释放锁
* sleep不释放锁
* notify()唤醒线程
* @author Administrator
*
*/
public class Movie {
private String pic;
private boolean Flag = true;
//信号灯
//Flag为true时,生产者开始生产,消费者等待
//Flag为false时,消费者开始消费,生产者等待
public synchronized void play(String pic) {
while(!Flag) {
try {
this.wait(); //等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//开始生产
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产了" + pic);
//生产完毕
this.pic = pic;
Flag = false;
//通知消费者开始消费
this.notify();
}
public synchronized void watch() {
while(Flag) {
try {
this.wait(); //等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//开始生产
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//消费完毕
System.out.println("消费了" + pic);
this.Flag = true;
this.notify();
}
}
Player.java文件中源程序如下:
[java] view plain copy
package com.bjsxt.thread.pro;
public class Player implements Runnable {
private Movie m;
public Player(Movie m) {
super();
this.m = m;
}
@Override
public void run() {
for(int i=0;i<20;i++) {
if(0 == i%2) {
m.play("左青龙");
}else {
m.play("右白虎");
}
}
}
}
Watcher.java文件中源程序如下:
[java] view plain copy
package com.bjsxt.thread.pro;
public class Watcher implements Runnable {
private Movie m;
public Watcher(Movie m) {
super();
this.m = m;
}
@Override
public void run() {
for(int i=0;i<20;i++) {
m.watch();
}
}
}
App.java文件中源程序如下:
[java] view plain copy
package com.bjsxt.thread.pro;
public class App {
public static void main(String[] args) {
//共同的资源
Movie m = new Movie();
//多线程
Player p = new Player(m);
Watcher w = new Watcher(m);
Thread t1 = new Thread(p);
Thread t2 = new Thread(w);
t1.start();
t2.start();
}
}
运行结果
最终运行结果如下: