实例
要点
同步与线程的休眠
问题描述与分析
描述
生产者生产数据、消费者取走数据,四个线程,mian线程,jvm线程,生产者线程,消费者线程。
1、定义消费者和生产者线程不做处理,出现问题:商品还未生产完消费者就拿走了,两个线程没有同步资源,例如购票的错误,应该是生产者先生产完商品,消费者再进行消费。解决方法:同步。数据的生产及消费用同步方法写。
2、重复取数据,生产者还没来得及生产下一份数据消费者就来取数据了。想要得到的两个线程执行顺序是生消生消,但是顺序可能会紊乱。解决方法:固定顺序。在一个线程执行时让另外一个线程休眠。Object类的wait()方法和notify()方法。
代码
Info类
存储商品信息
public class Info {
private String name ="王兵";
private String content = "重庆邮电大学";
private boolean flag = false;
public synchronized void set(String name, String content) {
if (!flag) {
// 此时消费者未取走,生产者必须休眠
try{
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setContent(content);
flag = false;
super.notify();
}
public synchronized void get() {
if (flag) {
try {
super.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName() + "--->" + this.getContent());
flag = true;
super.notify();
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
生产者类
public class Producer implements Runnable{
private Info info = null;
public Producer(Info info) {
this.info = info;
}
@Override
public void run() {
boolean flag = false;
for (int i=0; i < 10; i ++) {
if (flag) {
info.set("王兵","重庆邮电大学");
flag = false;
}else{
info.set("软件工程学院","卓越工程师班");
flag = true;
}
}
}
}
消费者类
。
public class Comsumer implements Runnable{
private Info info = null;
public Comsumer(Info info) {
this.info = info;
}
@Override
public void run() {
for (int i = 1; i < 10; i ++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.info.get();
}
}
}
测试demo
。
public class ThreadCaseDemo {
public static void main(String[] args) {
Info info = new Info();
Producer producer = new Producer(info);
Comsumer comsumer = new Comsumer(info);
new Thread(producer).start();
new Thread(comsumer).start();
}
}