無邊界-生成者與消費者模式

  1. 簡述
    生成者消費者模式,在併發編程模式裏面很常見。無邊界是指消息隊列,沒有設置,具體大小。
    下面是常見的兩種模式

  2. 通用類

    MyTask : 定義了任務接口

package com.ricisung.Model.chapter1;

public abstract class MyTask {

    abstract void doSomething();

}

SayHelloTask: 它是MyTask 的實現類; 主要打印一句hello

package com.ricisung.Model.chapter1;

public class SayHelloTask extends MyTask {

    @Override
    void doSomething() {
        System.out.println(Thread.currentThread().getName() +" ...." +"say hello...");
    }


}
  1. 第一種消費者模式
    每個線程持有一個任務隊列。用消費代理分發給不同的線程處理,詳細如下:
    Customer
package com.ricisung.Model.chapter1;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.log4j.Logger;


public class Customer extends Thread {

    private static Logger logger = Logger.getLogger(Customer.class);

    private BlockingQueue<MyTask> queue = new LinkedBlockingQueue<MyTask>();

    public void putTask(MyTask task) throws InterruptedException {
        queue.add(task);
    }

    @Override
    public void run() {

        while (true) {
            try {
                MyTask task = queue.take();
                task.doSomething();

            } catch (Throwable e) {
                logger.error("",e);
            }
        }   
    }
}

消息代理: 消費者代理,隨機選取一個消費者,進行消費
CustomerProxy :

package com.ricisung.Model.chapter1;

import java.util.Random;

import org.apache.log4j.Logger;

public class CustomerProxy {
    private static Logger logger = Logger.getLogger(CustomerProxy.class);

    private static CustomerProxy instance = null;

    private Customer[] customers = null;

    private final int MAX_SIZE = 4;

    private CustomerProxy() {
        customers = new Customer[MAX_SIZE];
        for (int i = 0; i < MAX_SIZE; i++) {
            customers[i] = new Customer();
            customers[i].setDaemon(true);
            customers[i].start();
        }
    }


    public static synchronized CustomerProxy instance() throws InterruptedException {
        if (null == instance) {
            instance = new CustomerProxy();
        }
        return instance;
    }


    public void doWork(MyTask task) {
        int index = new Random().nextInt(MAX_SIZE);
        try {

            customers[index].putTask(task);

        } catch (Throwable e) {
            logger.error("",e);
        }
    }



}
  1. 第二種模式:只有消費代理有一個任務隊列,所有的線程都從消費代理的任務隊列中獲取任務。
    CustomerProxy1
package com.ricisung.Model.chapter1;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.log4j.Logger;

public class CustomerProxy1 {

    private static Logger logger = Logger.getLogger(CustomerProxy1.class);

    private static CustomerProxy1 instance = null;

    private Customer1[] customers = null;

    private final int MAX_SIZE = 4;

    private BlockingQueue<MyTask> queue = new LinkedBlockingQueue<MyTask>();

    private CustomerProxy1() {
        customers = new Customer1[MAX_SIZE]; 
        for (int i = 0; i < MAX_SIZE; i ++) {
            customers[i] = new Customer1();
            customers[i].setDaemon(true);
            customers[i].start();
        }

    }

    public static synchronized CustomerProxy1 instance() {
        if (null == instance) {
            instance = new CustomerProxy1();
        }
        return instance;
    }

    public void doWork(MyTask task) {
        try {
            queue.add(task);

        } catch (Throwable e) {
            logger.error("",e);
        }
    }


    class Customer1 extends Thread {

        @Override
        public void run() {

            while(true) {
                try {
                    MyTask task = queue.take();
                    task.doSomething();

                } catch (Throwable e) {
                    logger.error("",e);
                }
            }
        }

    }

}

Producer 生成者

package com.ricisung.Model.chapter1;


public class Producer {

    public static void main(String args[]) throws InterruptedException {
        //oneModel();
        twoModel();
    }

    public static void oneModel() throws InterruptedException {
        for (int i = 0; i < 100; i ++) {
            CustomerProxy.instance().doWork(new SayHelloTask());
        }

        Thread.sleep(1000 * 5);
    }

    public static void twoModel() throws InterruptedException {
        for (int i = 0; i < 100; i ++) {
            CustomerProxy1.instance().doWork(new SayHelloTask());
        }

        Thread.sleep(1000 * 5);

    }

}
  1. 測試結果:
    這裏寫圖片描述

  2. 兩種模式的比較
    兩種默認都可以有效的完成任務。
    第一種,每個線程都具有一個自己的任務隊列,這種模式相比第二種模式,CPU減少了在不同線程阻塞,減少了線程排隊同步問題。
    第二種,因爲多個線程同時共享了一個隊列,所以這種模式更充分的利用了線程; 第一種模式中一個線程完成任務了,就會立即阻塞,不會幫助其他線程共同完成任務;

如果多種任務同時存在,並且不同任務之間需要按相互先後順序,使用第一種模式就能很好的解決此類問題:將有依賴關係的任務放到同一個線程裏進行處理。

7.源碼下載地址
http://download.csdn.net/detail/jia281460530/9539500

發佈了49 篇原創文章 · 獲贊 13 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章