package com.github.netcomm.sponge; import java.util.HashMap; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class SpongeThreadPoolExecutor { public final static String FilePersistence_Dir = "directory"; public final static String BlockingQueue_Capacity = "capacity"; public final static String BlockingQueue_OnePersistLimit = "onePersistLimit"; public final static String MaxByteArray_Sz = "maxByteArray_Sz"; public final static String OneBatchWriteCnt = "oneBatchWriteCnt"; public final static String CanReleaseResMaxTime = "canReleaseResMaxTime"; public SpongeThreadPoolExecutor() { } /** * 创建一个默认以文件为持久化缓冲的线程池 * * @param corePoolSize 同java自带ThreadPoolExecutor初始化参数 * @param maximumPoolSize 同java自带ThreadPoolExecutor初始化参数 * @param keepAliveTime 同java自带ThreadPoolExecutor初始化参数 * @param timeUnit 同java自带ThreadPoolExecutor初始化参数 * @param parmHMap key-value方式的参数: * 1.FilePersistence_Dir: 持久化文件目录,如 d:/testThread、/root/netcomm; * 2.BlockingQueue_Capacity:存放在内存中的任务数量,默认500; * 3.BlockingQueue_OnePersistLimit:一次执行批量持久化的任务数上限,默认100; * 4.MaxByteArray_Sz:最大允许的内存数,单位byte,默认50 * 1024 * 1024(50M) * 5.OneBatchWriteCnt:进行一次持久化从内存队列中一批最多可以处理的个数,默认20 * 6.CanReleaseResMaxTime:如果连续等待这么长时间还没有任何持久化的读、写操作, * 则删除相关资源,如删除序列化的文件,默认60s。 * @return * @throws SpongeException */ public static ThreadPoolExecutor generateThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit timeUnit, HashMap parmHMap) throws SpongeException { //内存相关. 队列的容量,批量持久化的任务数 int tmpCapacity = 500; int tmpOnePersistLimit = 100; //文件相关: 目录,内存大小,每次持久化的数量 String tmpDirectory = null; long tmpMaxByteArray_Sz = 50 * 1024 * 1024; int tmpOneBatchWriteCnt = 20; int tmpCanReleaseResMaxTime = 60 * 1000; //这是我们这个类最终要得到的对象. 这里给这个类添加了多个自定义参数. 用来满足我们的队列缓冲功能. ThreadPoolExecutor tmpThreadPool = null; try { if (parmHMap != null) { tmpDirectory = (String) parmHMap.get(FilePersistence_Dir); if (tmpDirectory == null) { throw new SpongeException("parmHMap里缺少 " + FilePersistence_Dir + " 设置"); } String tmpCapStr = (String) parmHMap.get(BlockingQueue_Capacity); if (tmpCapStr != null) { tmpCapacity = Integer.parseInt(tmpCapStr); } String tmpLimit = (String) parmHMap.get(BlockingQueue_OnePersistLimit); if (tmpLimit != null) { tmpOnePersistLimit = Integer.parseInt(tmpLimit); } String tmpMaxByteArray_SzStr = (String) parmHMap.get(MaxByteArray_Sz); if (tmpMaxByteArray_SzStr != null) { tmpMaxByteArray_Sz = Long.parseLong(tmpMaxByteArray_SzStr); } String tmpOneBatchWriteCntStr = (String) parmHMap.get(OneBatchWriteCnt); if (tmpOneBatchWriteCntStr != null) { tmpOneBatchWriteCnt = Integer.parseInt(tmpOneBatchWriteCntStr); } String tmpCanReleaseResMaxTimeStr = (String) parmHMap.get(CanReleaseResMaxTime); if (tmpCanReleaseResMaxTimeStr != null) { tmpCanReleaseResMaxTime = Integer.parseInt(tmpCanReleaseResMaxTimeStr); } } else { throw new SpongeException("parmHMap 不能为null"); } //文件持久化策略 FilePersistence tmpFilePersistence = new FilePersistence(tmpMaxByteArray_Sz, tmpOneBatchWriteCnt, tmpCanReleaseResMaxTime, tmpDirectory); //SpongeService可以基于不同的实现类,比如文件,数据库,内存redis等. --> 服务基于策略 SpongeService tmpSpongeService = new SpongeService(tmpFilePersistence); //数组阻塞队列的自定义带缓冲实现 --> 服务会服务于队列 SpongeArrayBlockingQueue tmpMyArrayBlockingQueue = new SpongeArrayBlockingQueue(tmpCapacity, tmpOnePersistLimit, tmpSpongeService); //线程池的创建 --> 指定队列里的任务要从线程池中取出线程来执行任务 tmpThreadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, tmpMyArrayBlockingQueue); //初始化看看有没有需要消费的数据/任务. //什么叫做消费? 消费即读取数据. 因为数据的生产有三种介质: 队列,内存,磁盘. //数据先写到队列中,队列满了再写到内存,内存超过限制才写到磁盘. 在内存和磁盘中的数据就是我们要消费的数据. //因为数据一开始进入队列中,当大批量数据来临时,队列满了之后,如果溢出队列会导致数据丢失,所以我们保存到内存或磁盘中 //但是不能只是保存啊,因为放在队列中的数据要经过消费才有用.所以暂时保存到内存中的数据只有消费了才有用. //其实放到队列中的一般是要运行的任务,用队列的目的是让任务的到来和运行是有序的.将任务放到队列中称作生产者,取出队列的数据就是消费者了. //队列其实只是一个缓冲的作用,放入队列中的任务一定是会被取出来执行的(根据队列的策略是FIFO或者优先级等), //所以当队列满了之后,放到内存和磁盘中的任务也一定是被取出来执行的.否则任务只管添加到内存或磁盘中,没有取出来执行,内存和磁盘迟早会爆掉的. tmpMyArrayBlockingQueue.doFetchData_init(tmpThreadPool); } catch (Throwable ex) { ex.printStackTrace(); throw new SpongeException(ex.getLocalizedMessage()); } return tmpThreadPool; } public static ThreadPoolExecutor generateThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit timeUnit, HashMap parmHMap, PersistenceIntf thePersistenceInsParm) throws SpongeException { int tmpCapacity = 500; int tmpOnePersistLimit = 100; ThreadPoolExecutor tmpThreadPool = null; try { if (parmHMap != null) { String tmpCapStr = (String) parmHMap.get(BlockingQueue_Capacity); if (tmpCapStr != null) { tmpCapacity = Integer.parseInt(tmpCapStr); } String tmpLimit = (String) parmHMap.get(BlockingQueue_OnePersistLimit); if (tmpLimit != null) { tmpOnePersistLimit = Integer.parseInt(tmpLimit); } } if (thePersistenceInsParm == null) { throw new SpongeException("持久化插件不能为null"); } SpongeService tmpSpongeService = new SpongeService(thePersistenceInsParm); SpongeArrayBlockingQueue tmpMyArrayBlockingQueue = new SpongeArrayBlockingQueue(tmpCapacity, tmpOnePersistLimit, tmpSpongeService); tmpThreadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, tmpMyArrayBlockingQueue); tmpMyArrayBlockingQueue.doFetchData_init(tmpThreadPool); } catch (Throwable ex) { ex.printStackTrace(); throw new SpongeException(ex.getLocalizedMessage()); } return tmpThreadPool; } }