美文网首页
异步任务的正确使用

异步任务的正确使用

作者: 最美下雨天 | 来源:发表于2020-02-03 19:22 被阅读0次
    1、线程

    注意线程是可以设置优先级的

    new Thread(new Runnable() {
                @Override
                public void run() {
                    //设置线程优先级,减少与UI线程的竞争
                    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
                }
            }).start();
    
    
    

    特定场景下(例如App启动阶段为避免在主线程创建线程池的资源消耗)使用的话务必加上优先级的设置,而且在启动阶段这样创建线程的开销要小于创建线程池的开销

    2、正确使用AsyncTask

    参考:

    可以方便的进行线程切换,并且线程的优先级已经被默认设置成了:THREAD_PRIORITY_BACKGROUND,不会与UI线程抢占资源

    AsyncTask中的任务默认是放入ArrayDeque中,串行执行,正确使用AsyncTask的串行与并行

    3、线程池的使用
    package com.miduo.glidestudy;
    
    import android.os.Process;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    public class ThreadManager {
    
        private static ThreadPoolProxy mShortPool = null;
        private static Object mShortLock = new Object();
    
        public static void execute(final ThreadRunnable runnable)
        {
            getShortPool().execute(new Runnable() {
                @Override
                public void run() {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    runnable.doInBackGround();
                }
            });
    
    
        }
    
        abstract static class ThreadRunnable{
    
            abstract void doInBackGround();
    
        }
    
    
    
    
    
    
        /** 获取一个用于执行短耗时任务的线程池,避免因为和耗时长的任务处在同一个队列而长时间得不到执行,通常用来执行本地的IO/SQL */
        public static ThreadPoolProxy getShortPool() {
            synchronized (mShortLock) {
                if (mShortPool == null) {
                    mShortPool = new ThreadPoolProxy(2, 2, 5L);
                }
                return mShortPool;
            }
        }
    
        public static class ThreadPoolProxy {
            private ThreadPoolExecutor mPool;
            private int mCorePoolSize;
            private int mMaximumPoolSize;
            private long mKeepAliveTime;
    
            private ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {
                mCorePoolSize = corePoolSize;
                mMaximumPoolSize = maximumPoolSize;
                mKeepAliveTime = keepAliveTime;
            }
    
            /** 执行任务,当线程池处于关闭,将会重新创建新的线程池 */
            public synchronized void execute(Runnable run) {
                if (run == null) {
                    return;
                }
                if (mPool == null || mPool.isShutdown()) {
                    //参数说明
                    //当线程池中的线程小于mCorePoolSize,直接创建新的线程加入线程池执行任务
                    //当线程池中的线程数目等于mCorePoolSize,将会把任务放入任务队列BlockingQueue中
                    //当BlockingQueue中的任务放满了,将会创建新的线程去执行,
                    //但是当总线程数大于mMaximumPoolSize时,将会抛出异常,交给RejectedExecutionHandler处理
                    //mKeepAliveTime是线程执行完任务后,且队列中没有可以执行的任务,存活的时间,后面的参数是时间单位
                    //ThreadFactory是每次创建新的线程工厂
                    mPool = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
                }
                mPool.execute(run);
            }
    
            /** 取消线程池中某个还未执行的任务 */
            public synchronized void cancel(Runnable run) {
                if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {//(线程池没有关闭或者说正在关闭,但还没有完全关闭)
                    mPool.getQueue().remove(run);
                }
            }
    
            /** 判断线程池中是否包含指定的任务 */
            public synchronized boolean contains(Runnable run) {
                if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
                    return mPool.getQueue().contains(run);
                } else {
                    return false;
                }
            }
    
            /** 立刻关闭线程池,并且正在执行的任务也将会被中断 */
            public void stop() {
                if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
                    mPool.shutdownNow();
                }
            }
    
            /** 平缓关闭单任务线程池,但是会确保所有已经加入的任务都将会被执行完毕才关闭 */
            public synchronized void shutdown() {
                if (mPool != null && (!mPool.isShutdown() || mPool.isTerminating())) {
                    mPool.shutdown();
                }
            }
        }
    
    }
    
    

    参考

    线程的优先级具有继承性,在某线程中创建的线程会继承此线程的优先级。那么我们在UI线程中创建了线程池,其中的线程优先级是和UI线程优先级一样的;所以仍然可能出现20个同样优先级的线程平等的和UI线程抢占资源

    在上面的示例中,我们设置了线程池中的线程的优先级为
    THREAD_PRIORITY_BACKGROUND,AsyncTask就是这么用的

    相关文章

      网友评论

          本文标题:异步任务的正确使用

          本文链接:https://www.haomeiwen.com/subject/rjrhxhtx.html