android开发笔记之异步ThreadPoolExecutor

android开发笔记之异步ThreadPoolExecutorandroid异步开发android异步开发,主要有1.Thread+Handler进行异步处理2.继承Thread类和实现Runnable接口3.AsyncTask类4.RxJava5.AsyncQueryHandler但是事实上AsyncTask是有缺点的。syncTaskisdesignedtobeahelperclassaroundThreadandH…

大家好,又见面了,我是你们的朋友全栈君。

android异步开发

android异步开发,主要有
1.Thread+Handler进行异步处理
2.继承Thread类和实现Runnable接口
3.AsyncTask类
4.RxJava
5.AsyncQueryHandler

但是事实上AsyncTask是有缺点的。

syncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.

AsyncTask是一个帮助类,它非常适合一个后台短耗时操作(最多几秒)。如果你要使后台进程保持运行非常长的时间,强烈推荐你使用 Executor, ThreadPoolExecutor 和FutureTask。

所以下面我们就看看ThreadPoolExecutor 和FutureTask的使用方法.

ThreadPoolExecutor

我们直接查看android源码中ThreadPoolExecutor的使用情况:

grep -rni --include=*.java "ThreadPoolExecutor "  ./packages/ 
./packages/inputmethods/LatinIME/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java:113:    
private ThreadPoolExecutor mExecutor;
./packages/inputmethods/LatinIME/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java:124:        
// Executors#newSingleThreadExecutor creates a ThreadPoolExecutor but it returns the

具体我们查看关键的源码:
packages/inputmethods/LatinIME/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java

public final class DictionaryService extends Service {

    /**
     * An executor that serializes tasks given to it.
     */
    private ThreadPoolExecutor mExecutor;
    private static final int WORKER_THREAD_TIMEOUT_SECONDS = 15;

    @Override
    public void onCreate() {
        mExecutor = new ThreadPoolExecutor(1 /* corePoolSize */, 1 /* maximumPoolSize */,
                WORKER_THREAD_TIMEOUT_SECONDS /* keepAliveTime */,
                TimeUnit.SECONDS /* unit for keepAliveTime */,
                new LinkedBlockingQueue<Runnable>() /* workQueue */);
        mExecutor.allowCoreThreadTimeOut(true);
    }

    @Override
    public synchronized int onStartCommand(final Intent intent, final int flags,
            final int startId) {
            ........................
            mExecutor.submit(new Runnable() {
                @Override
                public void run() {
                ..........................
            });

其实上面也就给出了ThreadPoolExecutor 的一个使用样例了。

我们仿照上面的例子,写一个Demo:

我们使用ThreadPoolExecutor 来实现一个后台的60秒的耗时操作,然后再通过handler更新UI界面。

public class MainActivity extends AppCompatActivity {

    private final static String TAG = "MainActivity";

    private final static int UPDEAT_UI =1;

    private TextView textView;
    private Button button_ThreadPoolExecutor;

    private ThreadPoolExecutor mExecutor;
    private static final int WORKER_THREAD_TIMEOUT_SECONDS = 15;

    private  Handler handler =  new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch(msg.what){
                case UPDEAT_UI:
                    //Toast.makeText(getApplication(),"on do long funtion",Toast.LENGTH_LONG).show();
                    textView.setText("UPDEAT_UI--ThreadPoolExecutor");
                    Log.i(TAG,"handler.handleMessage--UPDEAT_UI");
                    break;
                default :
                    break;
            }
        }
    };

    private  Runnable runnable = new Runnable() {
        @Override
        public void run() {
            //on do long time function
            try {
                Thread.sleep(1000*60);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(TAG,"handler.sendEmptyMessage--UPDEAT_UI");
            handler.sendEmptyMessage(UPDEAT_UI);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        mExecutor = new ThreadPoolExecutor(
                1 /* corePoolSize */,
                1 /* maximumPoolSize */,
                WORKER_THREAD_TIMEOUT_SECONDS /* keepAliveTime */,
                TimeUnit.SECONDS /* unit for keepAliveTime */,
                new LinkedBlockingQueue<Runnable>() /* workQueue */);
        mExecutor.allowCoreThreadTimeOut(true);

        textView = (TextView) findViewById(R.id.textView);

        button_ThreadPoolExecutor = (Button) findViewById(R.id.button_ThreadPoolExecutor);
        button_ThreadPoolExecutor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.i(TAG,"button_ThreadPoolExecutor---onClick");
                //mExecutor.submit(runnable);
                mExecutor.execute(runnable);
            }
        });
    }
}

构造函数

ThreadPoolExecutor(
 int corePoolSize,
 int maximumPoolSize, 
 long keepAliveTime, 
 TimeUnit unit, 
 BlockingQueue<Runnable> workQueue,
  ThreadFactory threadFactory, 
  RejectedExecutionHandler handler) 

这个是ThreadPoolExecutor完整的构造器,其他的构造器其实也是在内部调用这个.

corePoolSize 核心线程数,线程池保留线程的数量,即使这些线程是空闲.除非设置了allowCoreThreadTimeOut
maximumPoolSize 线程池最大允许的线程数.
keepAliveTime 当当前的线程数大于核心线程数,那么这些多余的空闲的线程在被终止之前能等待新任务的时间.
unit keepAliveTime时间的单位
workQueue 这个是用来保留将要执行的工作队列.
threadFactory 用于创建新线程的工厂
handler 如果工作队列(workQueue)满了,那么这个handler是将会被执行.

Android中的线程池的分类

通过配置不同参数的ThreadPoolExecutor, 有4类常用的线程池, Executors类提供了4个工厂方法用于创建4种不同特性的线程池给开发者用.

FixedThreadPool
用法:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(num);
fixedThreadPool.execute(runnable对象);
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                              0L, TimeUnit.MILLISECONDS,
                              new LinkedBlockingQueue<Runnable>());
}

特点:只有核心线程数,并且没有超时机制,因此核心线程即使闲置时,也不会被回收,因此能更快的响应外界的请求.

CachedThreadPool
用法:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(runnable对象);
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                              60L, TimeUnit.SECONDS,
                              new SynchronousQueue<Runnable>());
}

特点:没有核心线程,非核心线程数量没有限制, 超时为60秒.
适用于执行大量耗时较少的任务,当线程闲置超过60秒时就会被系统回收掉,当所有线程都被系统回收后,它几乎不占用任何系统资源.

ScheduledThreadPool
用法:

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(int corePoolSize);
scheduledThreadPool.schedule(runnable对象, 2000, TimeUnit.MILLISECONDS);
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}

特点:核心线程数是固定的,非核心线程数量没有限制, 没有超时机制.
主要用于执行定时任务和具有固定周期的重复任务.

SingleThreadExecutor

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
singleThreadExecutor.execute(runnable对象);
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                            0L, TimeUnit.MILLISECONDS,
                            new LinkedBlockingQueue<Runnable>()));
}

特点:只有一个核心线程,并没有超时机制.
意义在于统一所有的外界任务到一个线程中, 这使得在这些任务之间不需要处理线程同步的问题.

Android中的四种线程池的使用源码

我们在源码中搜索ExecutorService,会发现大把的使用样例。下面我们就简单的列举几个吧。

Executors.newSingleThreadExecutor

packages\apps\SnapdragonGallery\src\com\android\photos\drawables\AutoThumbnailDrawable.java

private static ExecutorService sThreadPool = Executors.newSingleThreadExecutor();
sThreadPool.execute(mLoadBitmap);
.........................................
    private final Runnable mLoadBitmap = new Runnable() {
        @Override
        public void run() {
      
        }
    };

packages\apps\Contacts\src\com\android\contacts\vcard\VCardService.java

    // Should be single thread, as we don't want to simultaneously handle import and export
    // requests.
    private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
   ........................
   Log.d(LOG_TAG, "Executor service status: shutdown: " + mExecutorService.isShutdown()
                        + ", terminated: " + mExecutorService.isTerminated());
........................
    /**
     * Tries to call {@link ExecutorService#execute(Runnable)} toward a given processor.
     * @return true when successful.
     */
   private synchronized boolean tryExecute(ProcessorBase processor) {
        try {
            mExecutorService.execute(processor);
            return true;
        } catch (RejectedExecutionException e) {
            Log.w(LOG_TAG, "Failed to excetute a job.", e);
            return false;
        }
    }
........................
        Log.i(LOG_TAG, "No unfinished job. Stop this service.");
        mExecutorService.shutdown();
........................
        if (mExecutorService.isShutdown()) {
            Log.w(LOG_TAG, "MediaScanner update is requested after executor's being shut down. " +
                    "Ignoring the update request");
            return;
        }        
........................
mExecutorService.shutdown();

Executors.newCachedThreadPool

packages\apps\Dialer\java\com\android\voicemail\impl\fetch\FetchVoicemailReceiver.java

  private void fetchVoicemail(final Network network, final VoicemailStatus.Editor status) {
    Executor executor = Executors.newCachedThreadPool();
    executor.execute(
        new Runnable() {
          @Override
          public void run() {
         ................................................
          }
        });
  }

Executors.newFixedThreadPool

packages\apps\CMFileManager\src\com\cyanogenmod\filemanager\providers\SecureResourceProvider.java

private final ExecutorService mExecutorService = Executors.newFixedThreadPool(1);
...............................
mExecutorService.execute(new Runnable() {
                @Override
                public void run() {
                    ....................
                }
            });

Executors.newScheduledThreadPool

packages\apps\Dialer\java\com\android\dialer\app\voicemail\VoicemailPlaybackPresenter.java

private static ScheduledExecutorService mScheduledExecutorService;
......................
  private static synchronized ScheduledExecutorService getScheduledExecutorServiceInstance() {
    if (mScheduledExecutorService == null) {
      mScheduledExecutorService = Executors.newScheduledThreadPool(NUMBER_OF_THREADS_IN_POOL);
    }
    return mScheduledExecutorService;
  }
...........................
  /** Must be invoked when the parent activity is destroyed. */
  public void onDestroy() {
    // Clear references to avoid leaks from the singleton instance.
    mActivity = null;
    mContext = null;
    if (mScheduledExecutorService != null) {
      mScheduledExecutorService.shutdown();
      mScheduledExecutorService = null;
    }
 }

代码最后调用跳转到这个runnable:
\packages\apps\Dialer\java\com\android\dialer\app\voicemail\VoicemailPlaybackLayout.java

 /** Controls the animation of the playback slider. */
  @ThreadSafe
  private final class PositionUpdater implements Runnable {

    /** Update rate for the slider, 30fps. */
    private static final int SLIDER_UPDATE_PERIOD_MILLIS = 1000 / 30;

    private final ScheduledExecutorService mExecutorService;
    @GuardedBy("mLock")
    private ScheduledFuture<?> mScheduledFuture;

.........................
        mScheduledFuture = mExecutorService.scheduleAtFixedRate(
                this, 0, SLIDER_UPDATE_PERIOD_MILLIS, TimeUnit.MILLISECONDS);
...........................
      if (mScheduledFuture != null) {
        mScheduledFuture.cancel(true);
        mScheduledFuture = null;
      }

参考资料

1.Class ThreadPoolExecutor
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html
2.(十七)java多线程之ThreadPoolExecutor
https://segmentfault.com/a/1190000009111732
3.android中的线程池 ThreadPoolExecutor
https://www.jianshu.com/p/86eb8ea62141
4.ThreadPoolExecutor使用示例
https://cwind.iteye.com/blog/2286567

写在后面的话

为什么好久没有写博客,今天又开始写呢.

主要是最近看了一下一个Android面试一天一题,感觉这个作者android技术非常的棒,但是对技术还是这么热情.而对比自己,android技术的深度和广度都有欠缺,虽然平时开发没有什么问题,但是面试还是被别人diss.不一定别人就比我厉害,只是自己还是对一些平时有疑问的技术没有更深入的进一步了解.

就比如这个ThreadPoolExecutor 和FutureTask,其实早在几年前就想了解一下,但是就是没有进一步的去实践,那后面就再进一步把以前自己想做的事再做一次吧,去完成自己以前留下的小尾巴吧.

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/158706.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • kali更新源没有mysql_Kali更新源添加

    kali更新源没有mysql_Kali更新源添加    2.按键盘A进行对更新源的输入;3.常见的更新源如下:3.1中科大debhttp://mirrors.ustc.edu.cn/kalikali-rollingmainnon-freecontribdeb-srchttp://mirrors.ustc.edu.cn/kalikali-rollingmainnon-freecontrib3.2阿里云debhttp://m…

    2022年5月18日
  • 非局部均值滤波算法[通俗易懂]

    非局部均值滤波算法[通俗易懂]2016.09.09更新,修改了SSIM中值太大的问题首先谈一下什么是非局部均值滤波。在此之前,我们先来看一下均值滤波的原理。均值滤波均值滤波的计算非常简单,将图像像素点灰度记录在数组中,然后设置方框半径的值,然后将方框中的所有点的像素求和取平均,得到的结果就是均值滤波后对应像素点的灰度值。优点:计算很快而且简单从算法可以看出,只是求了平均,并没有很复杂的计算缺点:得到的图像很模

    2022年5月21日
  • 互联网金融风控模型

    互联网金融风控模型一、市场调研目前市面主流的风控模型1、互联网金融前10名排行榜(数据截止日期2017-09-12)互联网金融公司排名分别是蚂蚁金服、陆金所、京东金融、苏宁金融、百度金融、腾讯理财通、宜信、钱大掌柜、万达金融和网易理财。1.1蚂蚁金服1.1.1大数据技术对接第三方征信公司芝麻信用分,通过用户信用历史、行为偏好、履约能力、身份特质、人脉关系五个维度对…

    2022年6月14日
  • windows下thrift的使用(C++)

    windows下thrift的使用(C++)

    2021年11月19日
  • du查询文件夹占用空间,自动删除超过N天的文件「建议收藏」

    du查询文件夹占用空间,自动删除超过N天的文件

    2022年2月12日
  • .net 常用开源框架

    .net 常用开源框架Json.NETCodePlexArchiveJson.Net是一个读写Json效率比较高的.Net框架.Json.Net使得在.Net环境下使用Json更加简单。通过LinqToJSON可以快速的读写Json,通过JsonSerializer可以序列化你的.Net对象。让你轻松实现.Net中所有类型(对象,基本数据类型等)和Json的转换。Math.NETMath.NETMath.NET的目标是为提供一款自身包含清晰框架的符号运算和数学运算/科学运算,它是C#开发的开.

    2022年7月15日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号