Android中的线程和线程池
来源:互联网 发布:xp打开关闭windows功能 编辑:程序博客网 时间:2024/05/29 02:39
主线程的作用是运行四大组件:活动、服务、广播、内容提供器,以及它们和用户的交互,子线程主要是执行耗时操作,子线程也叫做工作线程
1.AsyncTask:
AsyncTask是方便开发者在子线程中更新UI,内部是封装了线程池和Handler
五个方法:
onPreExecute,在异步任务执行前执行,一般用于做一些准备工作
doInBackground方法是在线程池里执行的,通过publishProgress方法来发布进度消息给监听进度的方法
onProgressUpdate接受到publishProgress传递过来的进度后,在主线程里执行UI的更新
onPostExecute监听doInBackground方法执行完结束,并接受结果,然后在主线程对结果进行处理
onCancelled取消异步任务
用AsyncTask子类的实例的execute来执行异步,在执行完任务后就会关闭AsyncTask
注意事项:
AsyncTask的对象必须要在主线程中创建,这点很重要
Execute方法必须在UI线程调用
除了onCancelled方法,其他方法不要主动调用
一个AsyncTask对象只能执行一次,execute只能调用一次
AsyncTask是主要异步操作是执行在线程池里,一个AsyncTask执行线程池里的一个线程,这个线程池默认是串型的,也就是说,当有多个AsyncTask时,它们会一个个执行,不会并发执行;可以使用executeOnExecuter来代替execute方法,然后传递多一个指定的参数进去来让其进行并发操作
2.IntentService:
IntentService是可以更方便地执行后台任务,内部是采用HandlerThread来执行任务,单独地开启线程来执行后台任务容易被系统杀死,而放在服务里就不容易,这是IntentService的优点
HandlerThread是一个内部创建了消息循环的线程;在不需要时要quit结束它,因为它内部是一个无限循环
IntentService在执行完任务后会自动的停止,比较适合执行一些高优先级的后台任务;在实现上,IntentService封装了HandlerThread和Handler
IntentService也是顺序地执行后台任务的,当有多个IntentService时,会按照外界发起的顺序排队执行任务
继承自IntentService后要重写onHandleIntent方法
线程池地3大优点:
重用线程池中的线程,避免创建销毁带来的开销,即节约开销;
有效控制线程的最大并发数,避免量线程之间互抢资源导致阻塞,即控制并发访问资源;
管理,并提供定时执行以及执行间隔循环执行,即执行管理;
ThreadPoolExecutor(实现了ExecutorService接口)用来创建、初始化线程,需要指定几个参数来指定要创建的线程池的属性:
corePoolSize,核心线程的数量,核心线程池默认是一直存活的,可以通过设置allowCoreThreadTimeOut为true来根据keepAliveTime所设置的时间来回收核心线程
maximumPoolSize,最大线程池,达到这个值以后,后续的新线程会被阻塞
keepAliveTime,一般情况下只用来指定非核心线程的闲置时间
unit,用于指定keepAliveTime的时间单位
workQueue,任务队列
threadFactory,线程工厂,为线程池提供创建新线程的功能
ThreadPoolExecutor的执行过程如下:
如果线程的数量没有达到核心线程的数量,就创建核心线程
如果线程的数量达到了核心线程的数量,就会将任务放进任务队列中等待执行
如果线程的数量达到了核心线程的数量,并且任务队列也满了,就会创建一个非核心线程来执行任务
如果线程的数量达到了核心线程的数量,并且任务队列满了,并且非核心数量加上核心数量已经超过指定的最大线程数,就会拒绝任务
*需要注意的是,线程放进队列是当核心线程的数量够了时,而不是指定的最大线程数够了时,这里的线程是指核心线程;开启非核心线程是当队列满了时,而不是指定的核心线程数达到时。也就是说,队列是用来存放核心线程的,非核心线程没有队列,它是在核心线程不能够再多的时候才创建的
通过配置ThreadPoolExecutor可以实现很多特定的线程池,而Android中有4类常用的线程池,它们也是通过配置TPE来实现的:
FixedThreadPool,fixed的意思是固定的,也就是说是一个线程数量固定的线程池,而固定也就意味着它的线程都是核心线程,它们都不会被回收,没有超时机制
CachedThreadPool,缓存线程池,它和上一个完全相反,它只有非核心线程,它的数量可以任意大,有超时机制,这类线程池适合执行大量的耗时比较少的任务,当所有线程的任务执行完后,它几乎是不占用任何系统资源的,因为超时之后没有线程了
ScheduledThreadPool,规划线程池,它是有固定的核心线程,数量不限的非核心线程,适合执行定时任务和具有固定周期的重复任务
SingleThreadExecutor,单核线程池,它只有一个核心线程,也就是说,所有的任务都要这个线程来处理,这样可以保证任务的按顺序执行,适合必须要顺序执行的任务
上面4种方法使用多态的创建:ExecutorService xxx = Executors.new+上述线程池名称(需要的数量参数); 然后xxx.execute(没有调用开始方法的任务Runnable/Callable/Thread实例和必要的配置参数)来使用
另外一种方式是调用submit方法:
Future<?> submit(Runnable task) (Future为null,这个方法其实没有返回值)
Future<T> submit(Runnable task, T result)
Future<T> submit(Callable<T> task)
方法返回一个Future对象,可以使用该Future对象进行线程池控制,比如调用Future对象的isDone判断是否执行完,用cancel取消任务,用isCancel判断是否被取消等
当某个线程池执行已经不需要再使用时,使用该线程池对象的shutdown关闭
- Android中的线程和线程池
- Android中的线程和线程池
- Android中的线程和线程池
- android中的线程和线程池
- Android中的线程和线程池及其源码分析:
- 源码分析Android中的线程和线程池
- Android 线程和线程池
- Android线程和线程池
- Android 线程和线程池
- Android线程和线程池
- Android线程和线程池
- Android 线程和线程池
- Android线程和线程池
- Android中的线程池
- Android中的线程池
- Android中的线程池
- Android 中的线程池
- Android中的线程池
- MySQL分配角色权限
- Hdu 6152 Friend-Graph(Ramsey定理)
- Android Touch 事件的分发和消费机制
- python网络编程
- 并发编程的三个概念
- Android中的线程和线程池
- Vector3.Lerp(When t = 0 returns a. When t = 1 returns b. When t = 0.5 returns the point midway betw)
- 深入理解操作系统虚拟内存
- Vector3.magnitude*vector3.up
- Linux GPIO Manipulation via Accessing Mapped Physical Memory
- PKG_CONFIG_PATH和PKG_CONFIG的路径设置问题
- Java学习笔记(二)——基础语法
- JAVA8新特性[第三季]-方法引用与构造器引用
- ML_week1