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。

所以下面我们就看看ThreadPoolExecutorFutureTask的使用方法.

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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 中国大推力矢量发动机WS15 跨入 世界先进水平!

    中国大推力矢量发动机WS15 跨入 世界先进水平!

    2021年12月5日
    466
  • 应用架构,业务架构,技术架构和业务流程图详解怎么写_业务架构和应用架构

    应用架构,业务架构,技术架构和业务流程图详解怎么写_业务架构和应用架构应用架构应用架构(ApplicationArchitecture)是描述了IT系统功能和技术实现的内容。应用架构分为以下两个不同的层次:企业级的应用架构:企业层面的应用架构起到了统一规划、承上启下的作用,向上承接了企业战略发展方向和业务模式,向下规划和指导企业各个IT系统的定位和功能。在企业架构中,应用架构是最重要和工作量最大的部分,他包括了企业的应用架构蓝图、架构标准/原则、系统的边界…

    2022年10月12日
    3
  • map集合遍历的三种方式(map遍历的两种方式)

    Map集合的遍历与List和Set集合不同。Map有两组值,因此遍历时可以只遍历值的集合,也可以只遍历键的集合,也可以同时遍历。Map以及实现Map的接口类(如HashMap、TreeMap、LinkedHashMap、Hashtable等)都可以用以下几种方式遍历。1)在for循环中使用entries实现Map的遍历(最常见和最常用的)。publicstati…

    2022年4月17日
    46
  • 个人觉得好用的Xmind快捷键(mac)[通俗易懂]

    个人觉得好用的Xmind快捷键(mac)[通俗易懂]commandN新建脑图空格修改文字Delete删除文字commandZ撤销上一步Enter添加平行分支Tab添加子节点command+/-放大/缩小commandI上传图片command+Shift+H插入超链接command+1,2,3,4,5,6快速添加优先等级图标-收缩目前分支方向键展开当前分支…

    2022年6月5日
    78
  • linux下如何完全删除用户

    linux下如何完全删除用户转载:http://blog.51cto.com/wutengfei/19234461、首先进入系统创建一个用户  [root@localhost/]#useraddhaha  #创建用户 haha是用户名   [root@localhost/]#passwdhaha  #为该用户设置密码  更改用户haha的密码。  新的密码:*****…

    2022年6月4日
    35
  • Android sdk_安卓sdk工具下载

    Android sdk_安卓sdk工具下载1在官网上获得软件压缩包imx-android-10.0.0_2.5.0.tar.gz下载地址2获取源码拷贝imx-android-10.0.0_2.5.0.tar.gz到一个文件夹里并解压,进入:2.1获取repogitclonehttps://mirrors.tuna.tsinghua.edu.cn/git/git-repo修改repo里的内容为下面REPO_URL=’https://mirrors.bfsu.edu.cn/git/git-repo’然后添

    2022年8月30日
    1

发表回复

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

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