关于Android中使用线程池对性能的优化以及线程池的原理,作用能理论,这里有一篇文章说得很透彻:
本文旨在介绍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