这次我们来基于java设计并实现一个简单的任务池。
什么叫任务池?
实际上就是一个任务流水线,可以将各种待完成的任务发布到流水线中。由任务池统计管理并且调度,来保证任务的完成。可能会有这样的疑问:我对每个任务都单独起一个线程,让其独立完成不就可以了么?对于小批量、快速、占用少量资源的任务可能这样没有问题,但是对于大规模、多并发的任务,这样的结果是会造成系统性能极其低下,并且还很可能造成资源需求上的溢出。
如何用有限的资源,调度并完成任务,这就是我们任务池的最终目标。
很直观,直接上任务池中就是有一个队列存储任务对象,对于每个任务它能知道当前任务状态(尚未开始、进行中、已完成)。当一个任务完成的时候,它将该任务清除,并且取出一个其他尚未完成的任务并开启之。
任务池应该具有并发性能,可以限制同时最多有多少个任务并行执行。
好,需求明确了,下面直接看代码吧。该代码实现子任务调用FFMPEG进行视频转码,而任务管理池用于限制并调度任务并发的执行。
/** * */ package com.nvvideo.upload.logic; import java.util.LinkedList; /** * TransferManager * <p>Title: 视频转码任务管理器</p> * <p>Description: </p> * <p>Date: 2010-7-14</p> * <p>Copyright: Copyright (c) 2010</p> * <p>Company: novel-supertv.com</p> * @author chenggong * @version 1.0 */ public class TransferManager { private int maxThreadNum = 1; private LinkedList<TransferTaskBase> fileList; private int workingThreadNum = 0; public TransferManager(){ this.fileList = new LinkedList<TransferTaskBase>(); } /** * 设置最大并发数 * @param num */ public void setMaxThreadNum( int num ){ this.maxThreadNum = num; } /** * 增加文件转码任务 * @param task */ public synchronized void addFileTask( TransferTaskBase task ){ fileList.addFirst(task); } /** * 启动转码任务 */ public void startTransfer(){ if( workingThreadNum >= maxThreadNum ) return; else{ transferNext(); } } private synchronized TransferTaskBase getNextFile(){ if( fileList.size() == 0 ) return null; else return fileList.removeLast(); } protected synchronized void threadLive(){ workingThreadNum++; } protected synchronized void threadFinish(){ workingThreadNum--; } /** * 启动下一个转码任务 */ public void transferNext(){ TransferTaskBase task = this.getNextFile(); if( task == null ){ return; } else{ task.start(); } } }
转码任务基类
package com.nvvideo.upload.logic; import com.nvvideo.logic.VideoLogic; import com.nvvideo.po.Video; /** * TransferTaskBase * <p>Title: 视频转码任务基类</p> * <p>Description: </p> * <p>Date: 2010-7-14</p> * <p>Copyright: Copyright (c) 2010</p> * <p>Company: novel-supertv.com</p> * @author chenggong * @version 1.0 */ public abstract class TransferTaskBase extends Thread { protected TransferManager manager; /** * 设置管理器 * @param manager */ public void setManager( TransferManager manager ){ this.manager = manager; } protected Video video; protected VideoLogic videoLogic; public void setVideo( Video video ){ this.video = video; } public void setVideoLogic(VideoLogic videoLogic) { this.videoLogic = videoLogic; } protected String originFileUri; /** * 设置源文件名 * @param filename */ public void setOriginFile( String filename ){ originFileUri = filename; } /* (non-Javadoc) * 开始执行转码任务 * @see java.lang.Thread#run() */ final public void run(){ manager.threadLive(); this.execute(); manager.threadFinish(); manager.transferNext(); } /** * 执行转码 * 必须以阻塞态执行 */ protected abstract void execute(); }
调用示例:
transferManager 任务池
task 具体任务
transferManager.addFileTask(task);
transferManager.startTransfer();