• 用阻塞队列和线程池简单实现生产者和消费者场景


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

    生产者消费者场景是我们应用中最常见的场景,我们可以通过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

  • 相关阅读:
    Python基础:01Python标准类型分类
    Python基础:05集合类型
    Python基础:04映射类型
    Python基础:03序列:字符串、列表和元组
    Python基础:02数字
    centreon公司推出的check plugin pack
    dell Nx000系列交换机
    交换机性能指标
    工作排班
    ansible
  • 原文地址:https://www.cnblogs.com/MindMrWang/p/8877731.html
Copyright © 2020-2023  润新知