• 解决Android中AsyncTask的多线程阻塞问题


    Android开发中执行耗时操作并更新UI时,通常有三种方式:
    1.直接调用runOnUiThread(new Runnable(){}),使用简单,但不能在Activity之外的环境使用,如View、Dialog等;
    2.使用AsyncTask实现,通过onPreExecute()、doInBackground()、onPostExecute三个方法能方便的分开UI操作和耗时操作,避免UI线程阻塞,并且支持参数传递;
    3.Handler结合Message实现,比较重量级,但还需要用到Looper等,而且Message封装的Bundle对象不能太大,否则会抛异常。
    几种方式各有利弊,实际开发中应根据需要选取合适方式,如Activity中可采用方法1和3,其他场合可使用方式2。

    公司的项目中最近经常出现数据加载不出来的问题,而且切换网络环境后,出现概率会变小,因此起初一直以为是HTTP请求模块的问题,将Socket的timeout设置为一分钟后,一开始确实没有再重现,但过了几天问题又重现了,于是通过转包并请后台API相关开发人员查看日志分析,发现请求根本都没发出去!这样进一步确定是APP这边的问题,但究竟出在哪里一片茫然。
    今天进行代码重构,涉及到AsyncTask这部分代码,通过logcat竟然发现onPreExecute()方法执行之后迟迟不进入doInBackground()方法!看来这就是问题所在。前一个task执行后,后一个task一直无法从pending状态进入running状态,说明线程阻塞了。
    仍然是从StackOverflow上找到了启示:
    API 11以前的AsyncTask线程池大小默认size为1,所以很容易阻塞,而之后的API提供了一个新方法executeOnExecutor(Executor exec, Params… params),第一个参数有两个常量值可选:
    1.SERIAL_EXECUTOR: 相当于之前的execute()方法,多个task串行,可能阻塞;
    2.THREAD_POOL_EXECUTOR: 线程池,默认size为5;
    这样我们可通过判断API Level调用不同的方法:

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    void startMyTask(AsyncTask asyncTask) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
            asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
        }else{
            asyncTask.execute(params);
        }
    }
    

    但是如果需要同时执行更多task(当然这个要尽量避免),仅仅使用AsyncTask也搞不定了,还需要通过BlockingQueue和ThreadPoolExecutor定义自己的线程池:

    int corePoolSize = 60;
    int maximumPoolSize = 80;
    int keepAliveTime = 10;
    BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(maximumPoolSize);
    Executor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue);
    asyncTask.executeOnExecutor(threadPoolExecutor);
    

    这样同时跑多个task线程就毫无压力了。

  • 相关阅读:
    Linus大神Win 7发布当天踢馆恶搞
    使用OpenSSL生成CSR文件,并申请全球通用SSL证书
    看Google的1000万.不是美元..是1000万台服务器!
    常见病毒 木马进程速查表
    GeoServer 2.0 正式版发布
    linux LiveCD 制作笔记
    开源WEB服务器lighttpd 1.4.24发布
    Nginx 的 server_names_hash_bucket_size 问题
    商业开源厂商最爱GPL,GPL并不能保证软件自由
    MySQL update回滚 mysqlbinlog回复数据
  • 原文地址:https://www.cnblogs.com/stevenlxq/p/3600847.html
Copyright © 2020-2023  润新知