生产者和消费者问题
实际案例:
两个在写多线程程序时容易犯的错误
- 当多个线程共同去操作同一份数据时,注意使用线程的同步保证信息的同步性和安全性。
- 遇到生产者和消费者这类问题,如果希望生产者生产之后立刻有消费者拿走,不出现重复生产与重复消费的现象,就需要使用Object的两个方法(唤醒和等待).当生产者生产玩一个信息后立刻有消费者读取此信息,需要有一个标志位。
package june_2th;
/** * 测试类 * @Hudie */
public class Test {
public static void main(String[] args) {
Movie movie = new Movie();
Thread producer = new Thread(new Producer(movie));
Thread consumer = new Thread(new Consumer(movie));
producer.start();
consumer.start();
}
}
package june_2th;
/** * 电影类 * * @Hudie */
public class Movie {
private String name;
private String info;
private boolean flag = true;// 设置标志位,控制生产者生成,消费者消费
public String getName() {
return name;
}
public String getInfo() {
return info;
}
// 该同步方法,可以为两个方法赋值
public synchronized void set(String name, String info) {
if (!flag) {
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.name = name;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info = info;
flag = false;// 重置标志位,让消费者消费
super.notify();// 唤醒消费者进程
}
public synchronized void get() {
if (flag) {
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(this.getName() + "-" + this.getInfo());
flag = true;
super.notify();
}
}
package june_2th;
/** * 生产者 * @Hudie */
public class Producer implements Runnable {
private Movie movie = null;
private boolean flag = false;
public Producer(Movie movie) {
super();
this.movie = movie;
}
@Override
public void run() {
// 循环录入五十遍电影数据,两部电影交替录入
for (int i = 0; i < 50; i++) {
if (flag) {
this.movie.set("变形金刚", "一部科幻电影");
flag = false;
} else {
this.movie.set("神偷奶爸", "一部3D动画电影");
flag = true;
}
}
}
}
package june_2th;
/** * 消费者 * @Hudie */
public class Consumer implements Runnable {
private Movie movie = null;
public Consumer(Movie movie) {
super();
this.movie = movie;
}
@Override
public void run() {
// 循环显示五十次电影信息
for (int i = 0; i < 50; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.movie.get();
}
}
}
测试结果: