5月11日学习总结——生产者与消费者

一、生产者与消费者模式

生产者将生产出来的信息不断存入一个区域内,消费者将信息从该区域内不断读取出来;

生产者录入信息

 消费者读取信息

生产者与消费者模式是一种经典同步案例, 它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题的方法可分为两类:(1)采用某种机制保护生产者和消费者之间的同步;(2)在生产者和消费者之间建立一个管道。第一种方式有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式。第二种管道缓冲区不易控制,被传输数据对象不易于封装等,实用性不强。

1、wait() / notify()方法

wait() / nofity()方法是基类Object的两个方法,也就意味着所有Java类都会拥有这两个方法,这样,我们就可以为任何对象实现同步机制。

wait()方法:当缓冲区已满/空时,生产者/消费者线程停止自己的执行,放弃锁,使自己处于等等状态,让其他线程执行。

notify()方法:当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。

2.线程同步

synchronized关键字,是一种同步锁。它修饰的对象有以下几种:

1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;

2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象;

3.实现步骤

1.第一步,首先让两个线程实现资源共享

2.第二步,解决线程并发问题

3.解决生产者和消费者依次进行的问题

volatile 修饰的属性为线程可见性属性

同步代码块synchronized()最好放在while里面,不然当一个线程一次获得了属性,就会将while循环执行完毕,所以同步代码块synchronized最好就只包括一次运行就结束的代码

实例代码:循环录入读取电影票

public class Movie {


private String name ;
private String info;
private boolean flag=true;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}

public void setInfo(String info) {
this.info = 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();
}

}

public class Productor implements Runnable{
private Movie movie=null;
boolean flag=false;

public Productor(Movie movie) {
super();
this.movie = movie;
}
public void run() {
for (int i = 0; i < 50; i++) {
if (flag) {
this.movie.set("变形金刚","一部科幻电影");

flag=false;
}else{
this.movie.set("神偷奶爸", "一部3d动画电影");
flag=true;
}
}

}


}

public class Consumer implements Runnable{
private Movie movie=null;



public Consumer(Movie movie) {
super();
this.movie = movie;
}

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();

}

}

}


public class Test {

public static void main(String[] args) {
Movie movie=new Movie();

Thread productor=new Thread(new Productor(movie));

Thread consumer=new Thread(new Consumer(movie));

productor.start();
consumer.start();

}
}



猜你喜欢

转载自blog.csdn.net/chenjingqi101/article/details/80305528
今日推荐