多线程模式之生产者-消费者模式

生产者-消费者模式为多线程之间协作提供了良好的解决方案,一般有2类线程,生产者类线程提交用户请求,消费者类线程则负责处理生产者线程提交的请求。
生产者-消费者模式架构图:




由图可见,生产者线程和消费者线程并不直接通信,内存缓存区充当二者的桥梁,将生产者线程和消费者线程解耦。同时由于内存缓存区的存在,也缓解了生产者和消费者之间的速度差异,从而一定程度上缓解了由于性能瓶颈对系统性能的影响。

代码示例:

PCData类:
public final class PCData {
    private final int intData;
    public PCData(int d){
        intData = d;
    }
    public PCData(String d){
        intData = Integer.valueOf(d);
    }
    public int getData(){
        return intData;
    }
    public String toString(){
        return "data="+intData;
    }
}


生产者线程:
public class Producer implements Runnable {
    private volatile boolean isRunning = true;
    private BlockingQueue<PCData> queue;
    private static AtomicInteger count = new AtomicInteger();
    private static final int SLEEPTIME = 1000;
    public Producer(BlockingQueue<PCData> queue){
        this.queue = queue;
    }
    public void run(){
        PCData data = null;
        Random r = new Random();
        System.out.println("start producer id = "+Thread.currentThread().getId());
        try{
            while(isRunning){
                Thread.sleep(r.nextInt(SLEEPTIME));
                data = new PCData(count.incrementAndGet());
                System.out.println(data + " is put to queue");
               if(!queue.offer(data,2, TimeUnit.SECONDS)){
                    System.out.println("failed to put data :"+data);
               }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
    }
    public void stop(){
        isRunning = false;
    }
}


消费者线程:
public class Consumer implements Runnable {
    private BlockingQueue<PCData> queue;
    private static final int SLEEPTIME = 1000;
    public Consumer(BlockingQueue<PCData> queue){
        this.queue = queue;
    }
    public void run(){
        System.out.println("start consumer id = " + Thread.currentThread().getId());
        Random r = new Random();
        try{
            while(true) {
                PCData data = queue.take();
                if (data != null) {
                    int re = data.getData() * data.getData();
                    System.out.println(MessageFormat.format("{0}*{1}={2}", data.getData(), data.getData(), re));
                    Thread.sleep(r.nextInt(SLEEPTIME));
                }
            }
        }catch(InterruptedException e){
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
    }
}


测试类:
public class Main {
    public static void main(String[] args) throws Exception{
        BlockingQueue<PCData> queue = new LinkedBlockingDeque<PCData>(10);
        Producer producer1 = new Producer(queue);
        Producer producer2 = new Producer(queue);
        Producer producer3 = new Producer(queue);

        Consumer consumer1 = new Consumer(queue);
        Consumer consumer2 = new Consumer(queue);
        Consumer consumer3 = new Consumer(queue);

        ExecutorService executor = Executors.newCachedThreadPool();
        executor.execute(producer1);
        executor.execute(producer2);
        executor.execute(producer3);
        executor.execute(consumer1);
        executor.execute(consumer2);
        executor.execute(consumer3);
        Thread.sleep(10 * 1000);
        producer1.stop();
        producer2.stop();
        producer3.stop();
        Thread.sleep(3000);
        executor.shutdown();
    }
}

测试类创建了3个生产者线程和3个消费者线程,LinkedBlockingDeque充当内存缓冲区的角色,两类线程都启动并运行起来后,在Thread.sleep(10 * 1000);时间内,生产者线程不停的往内存缓存中中提交数据,消费者线程不停的从内存缓冲区中取出数据并处理,Producer和Consumer类并不直接打交道,他们只同LinkedBlockingDeque打交道。






《Java性能优化》 葛一鸣

猜你喜欢

转载自frank1234.iteye.com/blog/2173259