Android中线程池使用ExecutorService

来源:互联网 发布:手机淘宝v5.10.0 编辑:程序博客网 时间:2024/05/24 07:40
关于Android中使用线程池对性能的优化以及线程池的原理,作用能理论,这里有一篇文章说得很透彻:
http://android.jobbole.com/82092/

本文旨在介绍Android中使用ExecutorService实现线程池及使用Runnable的Queue(建议在阅读本文之前先阅读上面文章补一下理论知识,老司机可忽略本提示~~~)。

1.执行多个AsyncTask
首先,Executors工厂类提供了五种功能不同的线程池,在附件demo的ExcutorTask类的构造方法中,分别创建了这相应的对象:
public ExcutorTask() {
// 每次只执行一条任务的线程池
singleTaskService = Executors.newSingleThreadExecutor();
// 每次执行限定个数任务的线程池
limitedTaskService = Executors.newFixedThreadPool(3);
// 根据实际情况调整线程池中线程的数量的线程池
allTaskService = Executors.newCachedThreadPool();
// 指定时间里执行任务的线程池,可重复使用
scheduledTaskService = Executors.newScheduledThreadPool(3);
// 返回一个可以控制线程池内线程定时或周期性执行某任务的线程池。只不过和上面的区别是该线程池大小为1
singleScheduledTaskService = Executors.newSingleThreadScheduledExecutor();
}

另外,该类提供了可以获取当前线程池的方法,线程池类型可以通过调用setServiceType(SERVICE_TYPE type)方法进行修改。
public ExecutorService getExecutor() {
if (mExecutor != null)
return mExecutor;
ExecutorService executor = limitedTaskService;
switch (type) {
case SINGLE:
executor = singleTaskService;
break;
case LIMITED:
executor = limitedTaskService;
break;
case ALL:
executor = allTaskService;
break;
case SCHEDULED:
executor = scheduledTaskService;
break;
case SINGLE_SCHEDULED:
executor = singleScheduledTaskService;
default:
break;
}
return executor;
}
附件的demo中的线程池中是同时执行的就是多个AsyncTask任务,AsyncTask使用ExcutorTask的方法也非常简单:
AsyTaskItem asyitem = new AsyTaskItem(item, position);
//添加任务
asyitem.executeOnExecutor(task.getExecutor());
list.add(asyitem);
运行效果如下图所示,实例中每次执行3个任务,执行完成以后,会继续执行下面的任务。


2.异步加载多张图片
该功能的实现封装在AsyncImageLoader中
private ExecutorService executorService = Executors.newFixedThreadPool(3);
该类使用了newFixedThreadPool实现了可以同时执行3个任务的线程池,并实现了使用SoftReference实现的软缓存保存Drawable对象;
public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
下面是加载图片的方法,如果缓存中有对应Drawable对象,直接从缓存中加载,否则从链接获取的流中解析出Drawable对象使用。
public void loadImage(final String url, final ImageCallback callback, final ImageView imageView) {
if (imageCache.containsKey(url)) {//有缓存
SoftReference<Drawable> soft = imageCache.get(url);
if (null != imageView)
imageView.setImageDrawable(soft.get());
if (callback != null) {
callback.onImageLoaded(soft.get());
}
} else {
executorService.execute(new Runnable() {

@Override
public void run() {
final Drawable drawable = loadFromURl(url);
imageCache.put(url, new SoftReference<Drawable>(drawable));
handler.post(new Runnable() {

@Override
public void run() {
if (null != imageView)
imageView.setImageDrawable(drawable);

if (callback != null) {
callback.onImageLoaded(drawable);
}
}
});
}
});
}
代码执行效果如下图所示:


3.RunnableQueue
该类实现了Runnable在Queue中列队执行的功能,可以通过addTask方法向Queue中添加任务:
public void addTask(final T mr) {
if (mES == null) {
mES = Executors.newSingleThreadExecutor();
notifyWork();
}

if (taskQueue == null) {
taskQueue = new ConcurrentLinkedQueue<>();
}

if (taskMap == null) {
taskMap = new ConcurrentHashMap<>();
}

mES.execute(new Runnable() {

@Override
public void run() {
/**
* 插入一个Runnable到任务队列中
* */
taskQueue.offer(mr);
// taskQueue.add(mr);
notifyWork();
}
});
}
通过调用start方法可以执行列队中的任务,直到taskQueue.poll()返回null
public void start() {
Log.v(TAG, "Queue Size --> " + taskQueue.size());
if (mES == null || taskQueue == null || taskMap == null) {
Log.i("KKK", "某资源是不是已经被释放了?");
return;
}
mES.execute(new Runnable() {
@Override
public void run() {
if (isRuning) {
T myRunnable = null;
synchronized (lock) {
// 从线程队列中取出一个Runnable对象来执行,如果此队列为空,则调用poll()方法会返回null
myRunnable = taskQueue.poll();
if (myRunnable == null) {
isNotify = true;
}
}

if (myRunnable != null) {
taskMap.put(mES.submit(myRunnable), myRunnable);
}
}

}
});
}
这里需要注意一下,在Runnable的run()方法中,当耗时的任务完成以后,要调用RunnableQueue中的remove()方法将当前任务从列队中移除。

CSDN上传文件失败,项目上传到github了:Android-ThreadPool-master

0 0