java多线程生产者与消费者案例_多线程操作实例——生产者与消费者

面对多线程学习生产者与消费者是最基本的实例

对于java后端开发的人员必须要掌握,还有考研考试计算机操作系统的同鞋。

下面是三个实例对于生产者与消费者的的例子,层层递进,逐步解决问题。

问题:生产者——设置信息名字name,和内容content

消费者——负责取出设置的信息。

一、基本实现

由于线程的不确定性可能出现以下问题:

(1)消费者取出的信息不匹配,即不是由同一个生产者设置的信息

(2)生产者生产了多个信息,消费者才开始取出信息,或消费者取出的重复的信息。

上面的问题下面会逐一解决,下面先看出现问题的程序:

packageli.xin.hua.ch9;/*线程生产者与向消费者最基本实现,问题有:

* 1、数据不匹配

* 2、数据重复取出已经取过的数据*/

classInfo{privateString name;privateString content;publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}publicString getContent() {returncontent;

}public voidsetContent(String content) {this.content =content;

}

};class Producer implementsRunnable{private Info info=null;publicProducer(Info info){this.info=info;

}public voidrun(){boolean flag=false;for(int i=0;i<10;++i)

{if(flag){this.info.setName("胡歌");try{

Thread.sleep(50);

}catch(InterruptedException e) {

e.printStackTrace();

}this.info.setContent("林殊");

flag=false;

}else{this.info.setName("刘涛");try{

Thread.sleep(50);

}catch(InterruptedException e) {

e.printStackTrace();

}this.info.setContent("郡主");

flag=true;

}

}

}

};class Consumer implementsRunnable{private Info info=null;publicConsumer(Info info){this.info=info;

}public voidrun(){for(int i=0;i<10;i++)

{try{

Thread.sleep(50);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(this.info.getName()+"---饰演--->"+this.info.getContent());

}

}

};public classProducer_Comsumer01 {public static voidmain(String[] args) {

Info info=newInfo();

Producer pro=newProducer(info);

Consumer con=newConsumer(info);newThread(pro).start();newThread(con).start();

}

}

运行结果如下图:

68e15ec8377f62daadd56b76747712f6.png

发现胡歌不仅饰演林殊,还饰演郡主,哈哈哈哈哈哈!

问题是线程生产的信息取出时是不匹配的,解决方法使用同步机制——synchronized

二、加入同步机制

将设置名称与内容定义在一个同步方法中,代码如下:

packageli.xin.hua.ch9;/*线程生产者与向消费者最基本实现

* 1、数据不匹配通过同步机制已经解决

* 2、重复取数据问题还是有*/

classInfo02{privateString name;privateString content;public synchronized voidget() {try{

Thread.sleep(50);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(this.name+"---饰演--->"+this.content);

}public synchronized voidset(String name,String content) {this.name=name;try{

Thread.sleep(50);

}catch(InterruptedException e) {

e.printStackTrace();

}this.content =content;

}

};class Producer02 implementsRunnable{private Info02 info=null;publicProducer02(Info02 info){this.info=info;

}public voidrun(){boolean flag=false;for(int i=0;i<10;++i)

{if(flag){this.info.set("胡歌","林殊");

flag=false;

}else{this.info.set("刘涛","郡主");

flag=true;

}

}

}

};class Consumer02 implementsRunnable{private Info02 info=null;publicConsumer02(Info02 info){this.info=info;

}public voidrun(){for(int i=0;i<10;i++)

{try{

Thread.sleep(50);

}catch(InterruptedException e) {

e.printStackTrace();

}this.info.get();

}

}

};public classProducer_Comsumer02 {public static voidmain(String[] args) {

Info02 info=newInfo02();

Producer02 pro=newProducer02(info);

Consumer02 con=newConsumer02(info);newThread(pro).start();newThread(con).start();

}

}

运行结果如下图:

b2e23d20ce68d1ac5dbc839c61574123.png

胡歌与刘涛饰演的角色没有匹配错误,但信息反复取出,需要Object类中的方法来解决。

三、加入等待唤醒机制

Object类中wait()、notify()方法,扩充点知识:wai()方法会释放线程的对象的锁,而sleep()方法不会。

设置一个标志位flag,

当flag为true时:

可以进行生产,但不能取出数据,若此时消费者线程恰巧抢到CPU资源,想要执行消费者程序,

必须将消费者线程等待wait()。生产者生产完成后要修改标示位(表示可以消费者可以取出信息了),和唤醒notify()被等待的线程。

当flag为false时:

消费者可以取出信息,但生产者不能生产信息,若此时生产者线程恰巧抢到CPU资源,想要执行生产者程序,

必须将生产者线程等待wait()。消费者完成取出信息后要修改标示位(表示可以生产者可以生产信息了),和唤醒notify()被等待的线程。

packageli.xin.hua.ch9;/*线程生产者与向消费者最基本实现

* 1、数据不匹配通过同步机制已经解决

* 2、重复取数据问题通过等待唤醒机制已经解决

* 当flag为true时允许生产者生产,若此时消费者进入则要等待

* 当flag为false时允许消费者取出信息,若此时生产者进入则要等待*/

classInfo03{privateString name;privateString content;private boolean flag=true; /*设置标示位:true是生产的时间,false是消费的时间。

第一次先生产*/

public synchronized voidset(String name,String content) {if(!flag) /*现在不是生产的时间,线程要等待,唤醒后才能生产。*/{try{super.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}this.name=name;try{

Thread.sleep(50);

}catch(InterruptedException e) {

e.printStackTrace();

}this.content =content;

flag=false;super.notify();

}public synchronized voidget() {if(flag) /*消费者*/{try{super.wait();

}catch(InterruptedException e) {

e.printStackTrace();

}

}try{

Thread.sleep(50);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(this.name+"---饰演--->"+this.content);

flag=true;super.notify();

}

};class Producer03 implementsRunnable{private Info03 info=null;publicProducer03(Info03 info){this.info=info;

}public voidrun(){boolean flag=false;for(int i=0;i<10;++i)

{if(flag){this.info.set("胡歌","林殊");

flag=false;

}else{this.info.set("刘涛","郡主");

flag=true;

}

}

}

};class Consumer03 implementsRunnable{private Info03 info=null;publicConsumer03(Info03 info){this.info=info;

}public voidrun(){for(int i=0;i<10;i++)

{try{

Thread.sleep(50);

}catch(InterruptedException e) {

e.printStackTrace();

}this.info.get();

}

}

};public classProducer_Comsumer03 {public static voidmain(String[] args) {

Info03 info=newInfo03();

Producer03 pro=newProducer03(info);

Consumer03 con=newConsumer03(info);newThread(pro).start();newThread(con).start();

}

}

运行结果如下图:

332989c1dc781143e5df56a47169a66e.png

胡歌与刘涛交替出现,并且角色匹配正确。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值