首先聲明,本人只是爲了鞏固知識而寫博客,如果你看了這篇博客對你有幫助,那麼我很開心,如果沒有幫助,那我也很遺憾,如果有錯誤很高興你指出來,只希望不要罵人,謝謝。
什麼是生產者和消費者
首先,我們都學過生物,顧名思義可以知道,生產者就是負責生產東西的,
消費者就是用來消費東西的。
生產者和消費者有什麼用
打個比方,我們去肯德基或者麥當勞點餐,那麼我們就是線程裏面的“消費者”,而那些負責製作食物的員工就是“生產者”
當我們點餐完成後,負責生產食物的人員不是去生產食物了,而是把之前生產好的食物搬到你的面前,然後你在開始進行用餐。
如果負責生產食物的人員發現食物的存儲量已經低於一個值,那麼這個時候,負責生產食物的人員就要開始去生產食物了,與此同時,消費者也要停止進餐,開始休息。
什麼是緩衝區
這個很容易理解就相當於裝食物的容器,我們去肯德基麥當勞點餐的時候,是不是會看見有一個大大的容器,裏面就是裝食物的,當我們把食物消滅到一定數量的時候,工作人員又開始繼續製作食物了。
看圖理解
代碼實現(容器)
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調度的時間不一樣,結果就不一樣,同時,消費者不會按照生產者生產的順序吃食物,是拿起來就是隨便吃,可能先吃第四個的時候,生產者下一波食物就生成了,他就直接吃了下一波的食物。
總結
總的來說,只需要控制好變量,這個並不是很難理解,但是要鎖對地方,如果鎖錯地方那麼就會出現錯誤的結果,這個是我第一次寫博客,寫的不好還請見諒,希望可以幫助到你。