多线程之线程池方式--练习生产者消费者模式

虽然Executor是个简单的接口,但它却为灵活且强大的异步任务执行框架提供了基础,该框架能支持多种不同类型的任务执行策略。它提供了一种标准的方法将任务的提交过程与执行过程解耦开来,并用Runnable来表示任务。

Executor基于生产者-消费者模式,提交任务的操作相当于生产者(生成待完成的工作单元),执行任务的线程则相当于消费者(执行完这些工作单元)。如果要在程序中实现一个生产者-消费者的设计,那么最简单的方式通常就是使用Executor。

线程池是与工作队列(Work Queue)密切相关的,其中在工作队列中保存了所有等待执行的任务。工作者线程的任务很简单:从工作队列中获取一个任务,执行任务,然后返回线程池并等待下一个任务。

这里主要理解将生产者和消费者解耦:
有了线程池后,线程都是从线程池中获取,减少了创建线程等操作的开销,提高响应。
阻塞队列的使用也使我们解耦更加方便了,而且不用管底层如何实现的wait,notify等,直接put添加,take获取就好啦。

写了个小例子,如有错误,请多指正。
(例子中的打印一般都不会加锁,虽然不是原子操作,但是不想因为打印让代码变得复杂)
可以发现和前面的生产者消费者代码相比,代码简便多了。

package com.cc.test.testThreadPool;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;


/**
 * @ClassName: TestThreadPool 
 * @Description: 练习线程池方式的生产者消费者
 * @author CC  
 * @date 2018年12月5日 上午9:39:54 
 * @version V1.0 
 */
public class TestThreadPool {
	private final static ExecutorService exec = Executors.newCachedThreadPool();//线程池
	
	private final static int BOUND = 1;//共享阻塞队列容量
	private final static LinkedBlockingQueue<List<String>> queue =  new LinkedBlockingQueue<List<String>>(BOUND);//共享阻塞队列
	
	private static volatile boolean isRunning = true;
	
	//初始化
	static{
		//生产者未生产会阻塞,不用管
		exec.execute(()->{
			while(true) {
				try {
					List<String> next = queue.take();
					System.err.println("消费者    消费 " + next.get(0) + "--" + next.get(next.size()-1));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
	public static void main(String[] args) {
		//数据库中获取数据并分隔
		VinDataList listData = new VinDataList();
		
		//一旦有数据开启生产者生产数据
		exec.execute(()->{
			for (List<String> list : VinDataList.getSizeDataList()) {
				try {
					System.out.println("生产者    生产 " + list.get(0) + "--" + list.get(list.size()-1));
					queue.put(list);
					Thread.sleep(300);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}	
		});
	}
}

//VinDataList这个类和之前一样,没有修改,这里再贴下吧
package com.cc.test.testThreadPool;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/*
 * 数据生成和处理类
 */
public class VinDataList {
	//基础数据初始化
	public static List<String> vinInfoVoList = new ArrayList<String>();
	static {
		for (int i = 0; i < 4300; i++) {
			vinInfoVoList.add(String.valueOf(i+1));
		}
	}
	
	private static int bucketSize = 500;
	
	//基础数据分割成500一份,方便操作
	private static List<List<String>> sizeDataList = new ArrayList<List<String>>();
	static {
		if(null != vinInfoVoList && vinInfoVoList.size() != 0) {
        	System.out.println("[存在待处理数据,进行生产者消费者模型处理]");
	        // 发布数据 
            String[] vinArr = (String[])vinInfoVoList.toArray(new String[vinInfoVoList.size()]);
            
            // 不能整除,分隔最后不足500的数据也为一次事件,也需要发布消费
            // 计算len的时候,需要依据查询接口实际返回的list的size计算,不能按照预期的size计算。比如预期4000条,实际返回了498条
            int len = ((vinInfoVoList.size() % bucketSize) == 0) ? (vinInfoVoList.size()/bucketSize) : (vinInfoVoList.size()/bucketSize + 1);
            for (int i = 0; i < len; i++) {//根据size分隔:500个为一个事件数据
            	String[] vinData =  null;
            	if((i+1)*bucketSize > vinInfoVoList.size()) {
            		vinData = Arrays.copyOfRange(vinArr, i*bucketSize , vinInfoVoList.size());
            	}else {
            		vinData = Arrays.copyOfRange(vinArr, i*bucketSize , (i+1)*bucketSize);
            	}
            	List<String> vinDataList = Arrays.asList(vinData);
            	sizeDataList.add(vinDataList);
    		}
		}else {
			System.out.println("[不存在待处理数据,请重新查询待处理数据]");
		}
	}
	public static synchronized List<String> next() {
		if(VinDataList.sizeDataList.size() > 0) {
			List<String> data = sizeDataList.get(0);
			sizeDataList.remove(0);
			return data;
		}
		return null;
	}
	
	public static void main(String[] args) {
		int i = 1;
		while(VinDataList.sizeDataList.size() > 0) {
			List<String> data = VinDataList.next();
			System.out.println(i + "-->" + data.size());
			i++;
		}
		
	}

	public static List<List<String>> getSizeDataList() {
		return sizeDataList;
	}
	
}


运行结果:
[存在待处理数据,进行生产者消费者模型处理]
生产者 生产 1–500
消费者 消费 1–500
生产者 生产 501–1000
消费者 消费 501–1000
生产者 生产 1001–1500
消费者 消费 1001–1500
生产者 生产 1501–2000
消费者 消费 1501–2000
生产者 生产 2001–2500
消费者 消费 2001–2500
生产者 生产 2501–3000
消费者 消费 2501–3000
生产者 生产 3001–3500
消费者 消费 3001–3500
生产者 生产 3501–4000
消费者 消费 3501–4000
生产者 生产 4001–4300
消费者 消费 4001–4300

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值