- AsyncTask: 为 UI 线程与工作线程之间进行快速的切换提供一种简单便捷的机制。适用于当下立即需要启动,但是异步执行的生命周期短暂的使用场景。
- HandlerThread: 为某些回调方法或者等待某些任务的执行设置一个专属的线程,并提供线程任务的调度机制。
- ThreadPool: 把任务分解成不同的单元,分发到各个不同的线程上,进行同时并发处理。
- IntentService: 适合于执行由 UI 触发的后台 Service 任务,并可以把后台任务执行的情况通过一定的机制反馈给 UI。
了解这些系统提供的多线程工具类分别适合在什么场景下,可以帮助我们选择合适的解决方案,避免出现不可预期的麻烦。虽然使用多线程可以提高程序的并发量,但是我们需要特别注意因为引入多线程而可能伴随而来的内存问题。举个例子,在 Activity 内部定义的一个 AsyncTask,它属于一个内部类,该类本身和外面的 Activity 是有引用关系的,如果 Activity 要销毁的时候,AsyncTask 还仍然在运行,这会导致 Activity 没有办法完全释放,从而引发内存泄漏。所以说,多线程是提升程序性能的有效手段之一,但是使用多线程却需要十分谨慎小心,如果不了解背后的执行机制以及使用的注意事项,很可能引起严重的问题。. Android 系统的屏幕刷新频率为 60 fps, 也就是每隔 16 ms 刷新一次。如果在某次绘制过程中,我们的操作不能在 16 ms 内完成,那它则不能赶上这次的绘制公交车,只能等下一轮。
这种现象叫做 “掉帧”,用户看到的就是界面绘制不连续、卡顿。
ThreadPoolExecutor
使用线程池的好处可以归纳为3点:
- 重用线程池中的线程, 避免因为线程的创建和销毁所带来的性能开销.
- 有效控制线程池中的最大并发数,避免大量线程之间因为相互抢占系统资源而导致的阻塞现象.
- 能够对线程进行简单的管理,可提供定时执行和按照指定时间间隔循环执行等功能.
不建议用ThreadPoolExecutor threadPoolExecutor= new ThreadPoolExecutor ();
而是用Executors工厂类方法
Executors类提供了4个工厂方法用于创建4种不同特性的线程池给开发者用.
区别:线程池的长度(线程的个数),可回收,是否处于等待状态,是否支持周期性
(1)newCachedThreadPool 创建一个可缓存线程池,线程池的最大长度无限制,但如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
(2) newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
(3)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
(4)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { @Overridepublic void run() { } },1, 2, TimeUnit.SECONDS);
常见几种BlockingQueue实现
1. ArrayBlockingQueue : 有界的数组队列
2. LinkedBlockingQueue : 可支持有界/无界的队列,使用链表实现
3. PriorityBlockingQueue : 优先队列,可以针对任务排序
4. SynchronousQueue : 队列长度为1的队列,和Array有点区别就是:client thread提交到block queue会是一个阻塞过程,直到有一个worker thread连接上来poll task。Executor和ExecutorService都是接口
Executor mThreadPool = Executors.newFixedThreadPool(3);
private ExecutorService mThreadPool = Executors.newFixedThreadPool(3);
public interface ExecutorService extends Executor {
建线程池管理者 ThreadManager
public class ThreadManager { public static final int POOL_SIZE = 2; public static ThreadManager mThreadManager = null; private ExecutorService mExeService = null; private int mCpuNum = 0; public static synchronized ThreadManager instance() { if (mThreadManager == null) { mThreadManager = new ThreadManager(); } return mThreadManager; } ThreadManager() { mCpuNum = Runtime.getRuntime().availableProcessors(); } public synchronized ExecutorService getExeService() { if (mExeService == null || mExeService.isShutdown()) { int threadNum = mCpuNum * POOL_SIZE; if (threadNum > 3) { threadNum = 3; } mExeService = Executors.newFixedThreadPool(threadNum); } return mExeService; }
实例:
/** * 请求百度推荐的应用 */ public void requestRecommendApp() { CXLog.d(TAG, "requestRecommendApp"); if (!mIsRequesting.get() && mIsExistAppInto) { mIsRequesting.set(true); mInfoAdapter.updateAppIntoStatus(); ThreadManager.instance() .getExeService() .submit(new Runnable() { @Override public void run() { List<ApkModel> apkModelList = mInfoAdapter.getRequestApkList(); if (apkModelList != null && apkModelList.size() > 0) { mApkNetworkUtil.requestIntoRecommendApp(apkModelList, getInstalledList()); if(CXConfig.DEBUG){ CXToastUtil.showToast(mContext,"请求服务器"); } } else { runOnUiThread(new Runnable() { @Override public void run() { if(CXConfig.DEBUG){ CXToastUtil.showToast(mContext,"直接导入"); } mInfoAdapter.intoReceiveApkList(null); intoFinish(); mIsExistAppInto = false; mIsRequesting.set(false); } }); } } }); } }
通过给线程加锁机制。来保证线程安全,以及当前程序当中只有一个x线程池ThreadPool
public class ThreadUtil { private static Executor threadPool = Executors.newCachedThreadPool(); public static void execute(Runnable runnable) { threadPool.execute(runnable); } }
升级版线程管理类:增加了同步机制
/** * 线程管理者。 * * @author peng * */ public class ThreadManager { private static ThreadPool threadPool; // 单列的线程池对象。 /** * 单列,线程安全 * 获取一个线程池对象 * @return */ public static ThreadPool getThreadPool() { if (threadPool == null) { //枷锁 synchronized (ThreadManager.class) { if (threadPool == null) { //核心线程数,等于处理器个数乘2 int corePoolSize = Runtime.getRuntime().availableProcessors()*2; int maximumPoolSize = 10; long keepAliveTime = 0L; threadPool = new ThreadPool(corePoolSize, maximumPoolSize, keepAliveTime); } } } return threadPool; } public static class ThreadPool { public static ThreadPoolExecutor executor = null; private int corePoolSize; private int maximumPoolSize; private long keepAliveTime = 0; // 限制线程的的最大存活时间 public ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime) { super(); this.corePoolSize = corePoolSize; //核心线程数 this.maximumPoolSize = maximumPoolSize; //最大线程 ,当核心线程用完时。决定是否开启最大线程 this.keepAliveTime = keepAliveTime; //线程排队时间, } /** * 线程池:就是把一堆线程放在一起来管理。 1.通过一定的管理机制。来处理线程额执行顺序 2.管理最多可以同时执行的线程数。 * 3.其他线程通过队列的形式,也就是排队的形式来管理线程的并发数。 * * @param runnable */ public void execute(Runnable runnable) { if (runnable == null) { return; } if (executor == null) { executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MILLISECONDS,// 时间单位 new LinkedBlockingQueue<Runnable>(),// 线程队列 Executors.defaultThreadFactory(),//线程工厂 new AbortPolicy()); } // 给线程池里面添加一个线程 executor.execute(runnable); } } }
Profile GPU Rendering : M Update
从 Android M 系统开始,系统更新了 GPU Profiling 的工具来帮助我们定位 UI 的渲染性能问题。早期的 CPU Profiling 工具只能粗略的显示出 Process,Execute,Update 三大步骤的时间耗费情况。
Android 性能优化<八> 多线程优化和线程管理
最新推荐文章于 2024-07-24 17:31:54 发布