在工作中我们经常会碰到并发处理的情况,如我们需要并发上传5张图片到文件服务器等待全部上传完毕后拿到返回链接再提交给逻辑服务器,这个时候5张图片的并发上传模型可以采用Callable+Future+CountDownLatch来处理,下面代码仅供参考学习。
/**
* @Description:等待全部子任务完成之后才返回的
*/
public abstract class BatchTask<T> {
public static final String TAG = "BaseFatherTask";
public static final SparseArray<BatchTask<?>> tasks = new SparseArray<BatchTask<?>>();
public static final AtomicInteger sequence = new AtomicInteger();
public final int taskId = sequence.getAndIncrement();
private ExecutorService subTaskExecutor;
private CountDownLatch countDown;
private ArrayList<Future<T>> subTaskResult = new ArrayList<Future<T>>();
private List<T> results = new ArrayList<T>();
private List<BaseChildTask<T>> childTaskList= new ArrayList<BaseChildTask<T>>();
private volatile boolean cancel = false;
public BatchTask(ExecutorService service) {
this.subTaskExecutor = service;
}
protected void cancel() {
if (childTaskList == null){
return;
}
cancel = true;
for( int i=0;i<childTaskList.size();i++) {
childTaskList.get(i).cancel();
}
}
/**
* 提交所有子任务
*
* @return true, 提交成功
*/
protected boolean submitChildTask(List<NewPostEntityProvider<T>> protocols) {
if (countDown != null ) {
NLog.e(TAG, "Already running task");
return false;
}
if (protocols == null || protocols.isEmpty()) {
return true; // 如果子任务列表为空,则返回执行成功
}
countDown = new CountDownLatch(protocols.size());
try {
for (NewPostEntityProvider<T> childTask : protocols) {
BaseChildTask<T> task = new BaseChildTask<T>(childTask, countDown);
Future<T> future = subTaskExecutor.submit(task);
childTaskList.add(task);
subTaskResult.add(future);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 等待子任务执行完成
*/
protected void waitSubTaskDone() {
if (countDown != null) {
try {
countDown.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 关闭线程池
*/
protected void shutDown() {
subTaskExecutor.shutdown();
}
/**
* 默认所有子任务执行成功才算成功,否则失败
*
* @return
*/
protected List<T> checkSubTask() {
for (Future<T> future : subTaskResult) {
T result = null;
try {
result = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
results.add(result);
}
return results;
}
/**
* @Description:子任务类,可以完成之后通知外面,只能用于@see BaseFatherTask 中创建
*/
private class BaseChildTask<T> implements Callable<T> {
private CountDownLatch countDownLatch;
private NewPostEntityProvider<T> provider;
public BaseChildTask(NewPostEntityProvider<T> provider, CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
this.provider = provider;
}
@Override
public T call() throws Exception {
if( !cancel) {
provider.send(true);
}
countDownLatch.countDown();
return provider.getResult();
}
public void cancel() {
if( provider != null) {
provider.cancel();
}
countDownLatch.countDown();
}
}
/* public static void cancelTask(int taskId) {
BatchTask<?> task = tasks.get(taskId);
if( task != null) {
task.cancel();
}
remove(taskId);
}
private static void remove(int taskId) {
tasks.remove(taskId);
}
public static int runTask(BatchTask<?> task) {
tasks.append(task.taskId, task);
new Thread(task).start();
return task.taskId;
}
*/
}