Java線程間同步實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者模式

字號(hào):

1.生產(chǎn)者-消費(fèi)者模式實(shí)現(xiàn)概述
    生產(chǎn)者與消費(fèi)者模式是我們?cè)诰幊踢^(guò)程中經(jīng)常會(huì)遇到的,就像我們生活那樣,生產(chǎn)者生產(chǎn)出產(chǎn)品,消費(fèi)者去購(gòu)買(mǎi)產(chǎn)品。在這里我們創(chuàng)建三個(gè)線程,一個(gè)主控線程main,用于創(chuàng)建各輔助線程;一個(gè)生產(chǎn)者線程,用于生產(chǎn)產(chǎn)品;一個(gè)消費(fèi)者線程,用于購(gòu)買(mǎi)產(chǎn)品。另外,我們創(chuàng)建一個(gè)隊(duì)列類Queue,生產(chǎn)線程生產(chǎn)的產(chǎn)品將放置到該隊(duì)列中,然后消費(fèi)者線程在該隊(duì)列中取走產(chǎn)品。
    2.實(shí)現(xiàn)該模式的要點(diǎn):
    首先必須讓生產(chǎn)者線程與消費(fèi)者線程達(dá)到同步,也就是說(shuō),當(dāng)生產(chǎn)者線程生產(chǎn)出產(chǎn)品后,消費(fèi)者才能去取,依此輪回。當(dāng)生產(chǎn)者線程放置產(chǎn)品到隊(duì)列中時(shí),隊(duì)列要檢查隊(duì)列是否已滿,如已滿,則等待消費(fèi)者線程將產(chǎn)品取走,否則放置產(chǎn)品到隊(duì)列中。當(dāng)消費(fèi)者線程在隊(duì)列中取產(chǎn)品時(shí),隊(duì)列也要檢查隊(duì)列是否為空,如果為空,則等待生產(chǎn)者線程放置產(chǎn)品到隊(duì)列,否則在隊(duì)列中取走產(chǎn)品。
    3.源代碼:
    class MainThread
    {
    public static void main(String[] args)
    {
    Queue queue=new Queue();
    Producer producer=new Producer(queue);
    Consumer consumer=new Consumer(queue);
    new Thread(producer).start();
    new Thread(consumer).start();
    }
    }
    /*注意:wait notify notifyAll只能在同步方法或內(nèi)步塊中調(diào)用*/
    class Queue
    {
    int product=0;
    boolean bfull=false;
    public synchronized void setProduct(int product)
    {
    if(bfull)//如果隊(duì)列已滿,則調(diào)用wait等待消費(fèi)者取走產(chǎn)品
    {
    try
    {
    wait();
    }
    catch(Exception e)
    {
    e.printStackTrace();
    }
    }
    /*開(kāi)始放置產(chǎn)品到隊(duì)列中*/
    this.product=product;
    System.out.println("Producer set product:"+product);
    bfull=true;
    notify();//生產(chǎn)產(chǎn)品后通知消費(fèi)者取走產(chǎn)品
    }
    public synchronized void getProduct()
    {
    if(!bfull)//如果隊(duì)列是空的,則調(diào)用wait等待生產(chǎn)者生產(chǎn)產(chǎn)品
    {
    try
    {
    wait();
    }
    catch(Exception e)
    {
    e.printStackTrace();
    }
    }
    /*開(kāi)始從隊(duì)列取走產(chǎn)品*/
    System.out.println("Consumer get product:"+product);
    bfull=false;
    notify();//取走產(chǎn)品后通知生產(chǎn)者繼續(xù)生產(chǎn)產(chǎn)品
    }
    }
    class Producer implements Runnable
    {
    Queue queue;
    Producer(Queue queue)
    {
    this.queue=queue;
    }
    public void run()//生產(chǎn)線程
    {
    for(int i=1;i<=10;i++)
    {
    queue.setProduct(i);
    }
    }
    }
    class Consumer implements Runnable
    {
    Queue queue;
    Consumer(Queue queue)
    {
    this.queue=queue;
    }
    public void run()//消費(fèi)線程
    {
    for(int i=1;i<=10;i++)
    {
    queue.getProduct();
    }
    }
    }
    輸出結(jié)果如下:
    Producer set product:1
    Consumer get product:1
    Producer set product:2
    Consumer get product:2
    Producer set product:3
    Consumer get product:3
    Producer set product:4
    Consumer get product:4
    Producer set product:5
    Consumer get product:5
    Producer set product:6
    Consumer get product:6
    Producer set product:7
    Consumer get product:7
    Producer set product:8
    Consumer get product:8
    Producer set product:9
    Consumer get product:9
    Producer set product:10
    Consumer get product:10