浅谈-----多线程(四)

来源:互联网 发布:ots工程师知乎 编辑:程序博客网 时间:2024/04/29 17:51

经典案例---生产者与消费者

大概情形:生产者不断生产,消费者不断取走生产者生产的产品。

大致如下:

存在问题:

①数据完整性问题。假设生产者线程刚向数据存储空间添加了信息的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程把信息的名称和上一个信息的内容联系在一起。

②重复取和重复设置的问题。生产者放了若干次的数据,消费者才开始取数据,或者是消费者取完一个数据后,还没等生产者放入新的数据,又重复取出已取过的数据。

程序基本实现

Info.java

class Info {private String name = "李兴华";private String content = "JAVA讲师";public String getName() {return name;}public void setName(String name) {this.name = name;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}}

Producer.java

public class Producer implements Runnable {private Info info = null;public Producer(Info info) {// TODO Auto-generated constructor stubthis.info = info;}@Overridepublic void run() {// TODO Auto-generated method stubboolean flag = false;for (int i = 0; i < 50; i++) {if(flag) {this.info.setName("李兴华");try {Thread.sleep(90);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}this.info.setContent("JAVA讲师");flag = false;} else {this.info.setName("mldn");try {Thread.sleep(90);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}this.info.setContent("www.mldnjava.cn");flag = true;}}}}

Consumer.java

public class Consumer implements Runnable {private Info info = null;public Consumer(Info info) {// TODO Auto-generated constructor stubthis.info = info;}@Overridepublic void run() {// TODO Auto-generated method stubfor (int i = 0; i < 50; i++) {try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(this.info.getName() + "-->"+ this.info.getContent());}}}


测试:

public class ThreadCaseDemo01 {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubInfo i = new Info();Producer pro = new Producer(i);Consumer con = new Consumer(i);new Thread(pro).start();new Thread(con).start();}}


得到:

问题出现了,怎么解决呢?

先来解决数据的完整性问题,在Info类中设置同步方法即可。

Info.java

class Info {private String name = "李兴华";private String content = "JAVA讲师";public String getName() {return name;}public void setName(String name) {this.name = name;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public synchronized void set(String name, String content) {this.setName(name);try {Thread.sleep(300);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}this.setContent(content);}public synchronized void get() {try {Thread.sleep(300);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(this.getName() + "-->" + this.getContent());}}

运行结果:

数据完整得到了解决,但是还是没解决重复取和重复设置问题。

这时,可以通过Object类对线程的支持来进行实现。

再次修改Info类,得到:

class Info {private String name = "李兴华";private String content = "JAVA讲师";private boolean flag = false;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public synchronized void set(String name, String content) {if(!flag) {try {super.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}this.setName(name);try {Thread.sleep(300);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}this.setContent(content);flag = false;super.notify();}public synchronized void get() {if(flag) {try {super.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}try {Thread.sleep(300);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(this.getName() + "-->" + this.getContent());flag = true;super.notify();}}

运行得到:

整个问题得到解决。




0 0
原创粉丝点击