zoukankan      html  css  js  c++  java
  • 用阻塞队列和线程池简单实现生产者和消费者场景

    本例子仅仅是博主学习阻塞队列和后的一些小实践,并不是真正的应用场景!

    生产者消费者场景是我们应用中最常见的场景,我们可以通过ReentrantLock的Condition和对线程进行wait,notify同通信来实现生产者和消费者场景,前者可以实现多生产者和多消费者模式,后者仅可以实现一生产者,一消费者模式。

    今天我们就利用阻塞队列来实现下生产者和消费者模式(里面还利用了线程池)。
    看过我关于阻塞队列博文的朋友已经知道,阻塞队列其实就是由ReentrantLock实现的!

    场景就不描述了,为简单的多生产者和多消费者!
    上代码:

    生产线程:

    public class ProductThread extends Thread {
    	private int taskNum;
    	private ArrayBlockingQueue queue;
    	public ProductThread(int taskNum,ArrayBlockingQueue queue) {
    		this.taskNum = taskNum;
    		this.queue = queue;
    	}
    	public void run() {
    		try {
    			//模拟生产
    			Thread.currentThread().sleep(5000);
    			System.out.println("开始生产");
    			queue.add(taskNum);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    消费线程:

    public class ConsumerThread extends Thread {
    	private ArrayBlockingQueue queue;
    	public ConsumerThread(ArrayBlockingQueue queue) {
    		this.queue = queue;
    	}
    	
    	public void run() {
    		System.out.println("准备消费");
    			int taskNum;
    			try {
    				taskNum = (int) queue.take();
    				System.out.println("消费了"+taskNum);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}	
    	}
    }
    

    主线程(主方法):

    public class ProductAndConsumer {
    	
    	public static void main(String[] args) {
    		ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(20);
    		//为多生产者和多消费者分别开创的线程池
    		ThreadPoolExecutor productPool = 
    				new ThreadPoolExecutor(10,20,60,TimeUnit.MILLISECONDS,new ArrayBlockingQueue(5),new ThreadPoolExecutor.CallerRunsPolicy());
    		ThreadPoolExecutor consumerPool = 
    				new ThreadPoolExecutor(10,20,60,TimeUnit.MILLISECONDS,new ArrayBlockingQueue(5),new ThreadPoolExecutor.CallerRunsPolicy());
    		
    		System.out.println("start");
    		for(int i = 0;i<100;i++) {
    			
    			productPool.execute(new ProductThread(i,queue));
    			consumerPool.execute(new ConsumerThread(queue));
    		}
    		productPool.shutdown();
    		consumerPool.shutdown();
    	}
    }
    

    上面的代码,我为生产者和消费者分别开了线程池,因为在实际的应用中可能出现生产者和消费者不对等的情况,所以我们应该根据实际情况来设定线程池的参数,以适应不同场景!
    在创建线程池的时候要加一个饱和处理的方式,我们上一节写线程池的饱和处理的时候有提及到,如果不加参数,会默认选择抛出异常,我上面选择的饱和策略是将饱和的任务交给调用线程(即主线程)处理,这个也应该根据实际情况来定,我们同样可以实现RejectedExecutionHandler接口,自己来定义这个饱和异常!

    以上仅是博主学习自己写的例子,可能在一些情况下考虑的不周到,还请指教!
    2018.4.18 21:31

  • 相关阅读:
    POJ1486 Sorting Slides 二分图or贪心
    POJ2060 Taxi Cab Scheme 最小路径覆盖
    POJ3083 Children of the Candy Corn 解题报告
    以前的文章
    POJ2449 Remmarguts' Date K短路经典题
    这一年的acm路
    POJ3014 Asteroids 最小点覆盖
    POJ2594 Treasure Exploration 最小路径覆盖
    POJ3009 Curling 2.0 解题报告
    POJ2226 Muddy Fields 最小点集覆盖
  • 原文地址:https://www.cnblogs.com/MindMrWang/p/8877731.html
Copyright © 2011-2022 走看看