后台可以有四个线程相同的时候管理AsyncTask

  • 原来的作品链接 : Using concurrency to improve speed and performance in
    Android
  • 初稿小编 : Ali Muzaffar
  • 译者 : edvardHua
  • 校对者: JOJO、Jing KE

图片 1

世家都清楚Android的UI更新是在UI线程中开展的。所以只要大家在UI线程中编辑耗费时间职责都或者会阻塞UI线程更新UI。为了防止这种情况我们能够利用
AsyncTask, IntentService和Threads。在前头本人写的一篇小说介绍了Android
中异步处理的8种方法。可是,Android提供的AsyncTasks和IntentService都是选择单一的后台线程来管理异步任务的。那么,开采职员怎样创立多个后台线程呢?

更新: 马尔科 Kotz 提出整合使用ThreadPool
Executor和AsyncTask,后台能够有四个线程同一时间管理AsyncTask。

创制二十四线程常用的诀要

在多数用到景况下,大家从不要求发出多少个后台线程,简单的创建AsyncTasks也许应用基于任务队列的IntentService就足以很好的满足大家对异步管理的须要。但是当我们真正须要多个后台线程的时候,大家经常会采用下边包车型地铁代码轻松的创办八个线程。

 String[] urls = … for (final String url : urls) { new Thread(new Runnable() { public void run() { // 调用API、下载数据或图片 } }).start(); }

该办法有多少个难题。一方面,操作系统限制了同一域下连接数。那象征,你的代码并不曾真正遵照你的意愿实施。新建的线程假设越过数量限制则须要等待旧线程实践达成。
其他,每贰个线程都被创立来实行一个任务,然后销毁。那么些线程也远非被圈定。

常用方法存在的主题材料

比方,如若你想付出一个连拍应用能在1分钟连拍10张图纸。应用该具有如下的子义务:

  • 在一秒的年华内扑捉10张以byte[]花样积存的相片,並且不可见阻塞UI线程。
  • 将byte[]累积的数目格式从YUV转换到PRADOGB。
  • 利用转变后的多少创制Bitmap。
  • 变换Bitmap的方向。
  • 变迁缩略图大小的Bitmap。
  • 将全尺寸的Bitmap以Jpeg压缩文件的格式写入磁盘中。
  • 利用上传队列将图纸保存到服务器中。

很掌握,假让你将太多的子任务放在UI线程中,你的应用在品质上的表现将不会太好。在这种情况下,独一的缓和方案正是先将相机预览的数量缓存起来,当UI线程闲置的时候再来利用缓存的数目实践剩下的天职。

别的多个可选的减轻方案是创制二个长日子在后台运转的HandlerThread,它亦可接受相机预览的数额,并拍卖完剩下的不论什么事职务。当然这种做法的性质会好些,可是纵然顾客想再连拍的话,将汇合前碰到非常大的推迟,因为他索要等待HandlerThread管理完前贰次连拍。

 public class CameraHandlerThread extends HandlerThread implements Camera.PictureCallback, Camera.PreviewCallback { private static String TAG = "CameraHandlerThread"; private static final int WHAT_PROCESS_IMAGE = 0; Handler mHandler = null; WeakReference<camerapreviewfragment> ref = null; private PictureUploadHandlerThread mPictureUploadThread; private boolean mBurst = false; private int mCounter = 1; CameraHandlerThread(CameraPreviewFragment cameraPreview) { super; start(); mHandler = new Handler(getLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message msg) { if (msg.what == WHAT_PROCESS_IMAGE) { // 业务逻辑 } return true; } }); ref = new WeakReference<>(cameraPreview); } ... @Override public void onPreviewFrame(byte[] data, Camera camera) { if  { CameraPreviewFragment f = ref.get(); if (f != null) { mHandler.obtainMessage(WHAT_PROCESS_IMAGE, data) .sendToTarget(); try { sleep; } catch (InterruptedException e) { e.printStackTrace(); } if (f.isAdded { f.readyForPicture(); } } if (mCounter++ == 10) { mBurst = false; mCounter = 1; } } } }

提醒:
若是你必要上学更加多有关于HandlerThreads内容以及怎样行使它,请阅读笔者公布的关于HandlerThreads的小说。

看起来全数的职分都被后台的单一线程管理完毕了,大家质量升高首要得益于后台线程长期运营并不会被消亡和重新建设构造。然则,大家后台的单一线程却要和别的优先品级越来越高的职务分享,并且那一个任务只好够顺序试行。

咱俩也能够创设第贰个HandlerThread来拍卖我们的图像,然后创设第多少个HandlerThread来将照片写入磁盘,最后再次创下设第多少个HandlerThread来将照片上传播服务器中。大家能够加快拍照的快慢,不过,那一个线程相互之间还是遵从顺序施行的条条框框,并非当真出现。因为每张照片是各种管理的,並且管理每一张照片须要一定的时日,导致客商在点击拍照按键到显示全部缩略图的时候还是能够领悟的认为到延迟。

利用ThreadPool并发管理义务

咱俩得以依附须要创设多少个线程,不过创建过多的线程会开销CPU周期影响属性,何况线程的始建和销毁也急需时日本资本产。所以大家不想创建多余的线程,然而又想能够丰盛的利用设备的硬件财富。那年大家能够运用ThreadPool。

通过创制ThreadPool对象的单例来在您的应用中利用ThreadPool。

 public class BitmapThreadPool { private static BitmapThreadPool mInstance; private ThreadPoolExecutor mThreadPoolExec; private static int MAX_POOL_SIZE; private static final int KEEP_ALIVE = 10; BlockingQueue<runnable> workQueue = new LinkedBlockingQueue<>(); public static synchronized void post(Runnable runnable) { if (mInstance == null) { mInstance = new BitmapThreadPool(); } mInstance.mThreadPoolExec.execute; } private BitmapThreadPool() { int coreNum = Runtime.getRuntime().availableProcessors(); MAX_POOL_SIZE = coreNum * 2; mThreadPoolExec = new ThreadPoolExecutor( coreNum, MAX_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, workQueue); } public static void finish() { mInstance.mThreadPoolExec.shutdown(); } }

下一场,在上头的代码中,轻巧的修改Handler的回调函数为:

 mHandler = new Handler(getLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message msg) { if (msg.what == WHAT_PROCESS_IMAGE) { BitmapThreadPool.post(new Runnable() { @Override public void run() { // 做你想做的任何事情 } }); } return true; } });

优化已经做到!通过上面包车型地铁录像,我们着重到加载缩略图的速度提高是特别鲜明的。

这种做法的独到之处是大家得以定义线程池的大大小小况兼钦赐空余线程保持活动的年华。大家也得以创建多个ThreadPools来管理多个职务依旧使用单个ThreadPool来拍卖多少个职责。可是在选拔完后回想清理财富。

咱俩如故足以为每叁个效果创建二个独自的ThreadPool。举个例子说在那么些事例中大家得以创设四个ThreadPool,第4个ThreadPool担当数据转变到Bitmap,第二个ThreadPool担当写多少到磁盘中去,第多少个ThreadPool上传Bitmap到服务器中去。那样做的话,假使大家的ThreadPool最大有所4条线程,那么大家就能够同时的调换,写入,上传四张相片。顾客将看见4张缩略图是还要突显并非一个个的展现出来的。

上边那几个轻巧例子代码能够在自己的GitHub上赢得,接待看完代码后给自家报告

另外,你也得以在Google Play上面下载演示应用。

使用ThreadPool前:
如若得以,从最上端观望计数器的调换来获知当尾巴部分缩略图从开端呈现到任何来得成功所消耗的时刻。在程序中除了adapter中的notifyDataSetChanged()方法外,小编一度将大部分的操作从主线程中脱离,所以计数器的运作是很通畅的。)

使用ThreadPool后:
通过顶上部分的计数器,大家发掘选择了ThreadPool后,照片的缩略图加载速度分明变快。)

最后

一旦想要开辟更增加速度的应用程序, 请阅读作者的小说.

小说已经到底了,在Medium上Follow小编啊。 LinkedIn, 谷歌(Google)+ or 推特.

相关文章