首先声明,本人只是为了巩固知识而写博客,如果你看了这篇博客对你有帮助,那么我很开心,如果没有帮助,那我也很遗憾,如果有错误很高兴你指出来,只希望不要骂人,谢谢。
什么是生产者和消费者
首先,我们都学过生物,顾名思义可以知道,生产者就是负责生产东西的,
消费者就是用来消费东西的。
生产者和消费者有什么用
打个比方,我们去肯德基或者麦当劳点餐,那么我们就是线程里面的“消费者”,而那些负责制作食物的员工就是“生产者”
当我们点餐完成后,负责生产食物的人员不是去生产食物了,而是把之前生产好的食物搬到你的面前,然后你在开始进行用餐。
如果负责生产食物的人员发现食物的存储量已经低于一个值,那么这个时候,负责生产食物的人员就要开始去生产食物了,与此同时,消费者也要停止进餐,开始休息。
什么是缓冲区
这个很容易理解就相当于装食物的容器,我们去肯德基麦当劳点餐的时候,是不是会看见有一个大大的容器,里面就是装食物的,当我们把食物消灭到一定数量的时候,工作人员又开始继续制作食物了。
看图理解
代码实现(容器)
class RQ //定义一个容器类
{
Egg[] eggs=new Egg[10]; //new一个鸡蛋数组就十个吧,鸡蛋类会在下面写到
int count =1; //一开始有一个鸡蛋
public synchronized void push(Egg egg ) throws InterruptedException {
if(count==eggs.length) {
this.wait();//如果鸡蛋的数量等于数组的长度,也就是十,线程开始等待,这个时候下面的代码不会执行
}
//当这个线程被唤醒,开始执行
eggs[count]=egg;//
count++;
this.notifyAll();
}
public synchronized Egg pop() throws InterruptedException {
if(count==1)
{
this.wait();//如果鸡蛋只有一个,那么线程开始等待
}
//线程被唤醒后开始执行
count--;
Egg egg=eggs[count];
this.notifyAll();
return egg;
}
}
代码实现(生产者)
class scz implements Runnable
{
RQ rq =new RQ();//先new一个容器
public scz(RQ rq) {
this.rq = rq;
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println("生产了第--->"+i+"个鸡蛋");
try {
rq.push(new Egg(i));//没生产一个鸡蛋,就调用rq函数的push,并且把i传入到Egg的id里面;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
代码实现(消费者)
class xfz implements Runnable
{
RQ rq =new RQ();//new一个容器
public xfz(RQ rq) {
this.rq = rq;
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
try {
System.out.println("消费了第--->"+rq.pop().id+"个鸡蛋");
//如果是写i的话那么消费者吃掉的鸡蛋就和生产者生产的数量没关系
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
代码实现(鸡蛋)
class Egg
{
int id=0;
public Egg(int id) {
this.id = id;
}
}
全部代码总和
package Thread;
public class mytest01 {
public static void main(String[] args) {
RQ rq=new RQ();
scz s=new scz(rq);
xfz x =new xfz(rq);
Thread t1=new Thread(s);
Thread t2=new Thread(x);
t1.start();
t2.start();
}
}
class scz implements Runnable
{
RQ rq =new RQ();
public scz(RQ rq) {
this.rq = rq;
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println("生产了第--->"+i+"个鸡蛋");
try {
rq.push(new Egg(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class xfz implements Runnable
{
RQ rq =new RQ();
public xfz(RQ rq) {
this.rq = rq;
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
try {
System.out.println("消费了第--->"+rq.pop().id+"个鸡蛋");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class RQ
{
Egg[] eggs=new Egg[10];
int count =1;
public synchronized void push(Egg egg ) throws InterruptedException {
if(count==eggs.length) {
this.wait();
}
eggs[count]=egg;
count++;
this.notifyAll();
}
public synchronized Egg pop() throws InterruptedException {
if(count==1)
{
this.wait();
}
count--;
Egg egg=eggs[count];
this.notifyAll();
return egg;
}
}
class Egg
{
int id=0;
public Egg(int id) {
this.id = id;
}
}
结果
每一次运行结果都会是不一样的,因为每次cpu调度的时间不一样,结果就不一样,同时,消费者不会按照生产者生产的顺序吃食物,是拿起来就是随便吃,可能先吃第四个的时候,生产者下一波食物就生成了,他就直接吃了下一波的食物。
总结
总的来说,只需要控制好变量,这个并不是很难理解,但是要锁对地方,如果锁错地方那么就会出现错误的结果,这个是我第一次写博客,写的不好还请见谅,希望可以帮助到你。