1、线程:CPU调度的最小单元。
2、特点:线程是一种受限的系统资源,也就是说线程不能无限的创建和销毁
问: 如何避免频繁的创建和销毁线程所带来的系统
答:采用线程池,线程池中缓存了一定数量的线程,进而达到效果。
3、线程池
假如一个服务器完成一项任务所需要的时间为:T1创建线程的时间,T2在线程中执行任务的时间,T3销毁线程的时间
如果:T1+T3远大于T2,则可以采用线程池,以提高服务器的性能
线程池的技术正是关注如何缩短和调整T1,T3时间的技术,从而提高服务器程序的性能。它把T1,T3分别安排在服务器程序的启动和结束的时间或者在一些空闲的时间里面。这样在服务器程序处理客户请求的时候,就不会有T1,T3的开销了。
优点:
- 重用线程池中的线程,避免线程的创建和销毁带来的性能消耗
- 有效的控制线程池的最大并发数,避免大量的线程之间因相互抢占系统资源而到最后阻塞现象
- 进行线程的统一管理,提供定时、循环间隔执行等功能
2、线程池的概念
java中的Executer,它是一个接口
线程池的真正实现:ThreadPoolExecuter,它提供了一系列参数来配置线程池
- corePoolSize:核心线程
默认情况下,一直存活。
当设置ThreadPoolExecutor的allowsCoreThreadTimeOut属性为
true:表示核心线程闲置时间超过超时的时长,就会被回收
false:表示核心线程不会被回收,一直都会在线程中存活
maximumPoolSize:最大线程数
当活动线程数达到这个数值后,后续的任务将会被阻塞keepAliveTime:非核心线程超时时间
超过这个时间,闲置的非核心线程就会被回收
当设置ThreadPoolExecutor的allowCoreThreadTimeTout属性为true时,keepAliveTime对核心线程同样有效unit:用于指定keepAliveTime的时间单位
单位有:TimeUnit.MILLISECONDS、TimeUnit.SECONDS、TimeUnit.MINUTES等;workQueue:任务队列
通过线程池的excute()方法提交的Runnable对象都会存储在这个参数中threadFactory:线程工程,可创建新线程
是个接口,只有一个方法 Thread newThread(Runnable r)handler:在线程池无法执行新任务时进行调度
ThreadPoolExecutor的默认工作策略
若线程池中的线程数量未达到核心线程数,则会直接启动一个核心线程执行任务
若线程中的线程数据已达到或者超过核心数线程,则这个任务会被插入到任务列表等待执行
若任务无法插入到任务列表中,往往是由于任务列表已经满了,此时如果
线程数量未达到线程池最大的线程数,则会启动一个非核心线程执行任务
线程数量已经达到线程池规定的最大值,则拒绝执行此任务
四种线程池的分类
FixThreadPool:
线程数量固定的线程池,所有的线程都是核心线程,当线程空闲的时候不会被回收。
特点:能快速响应外界的请求CacheThreadPool
线程数量不定的线程池,只有非核心线程,空闲线程有超时机制,超时能回收
特点:适用于执行大量的耗时时间少的任务ScheduledThreadPool
核心线程数量固定,非核心线程数量不定
特点:定时任务和定时周期的任务SingleThreadExecutor
只有一个核心进程,可确保所有的任务都在同一个线程中按顺序执行
特点:无需处理线程同步的问题
Android中的ANR异常
ANR,即应用程序无响应。系统会向用户显示一个对话框,用户可以选择“等待”,或者“强制关闭”
在Android中,应用程序是ActivityManager和WindowManager系统服务监视的。
- 在5秒内没有响应输入事件(屏幕按下,触摸等)
- 在10秒内BroadCastReiceiver没有执行完毕
- 在20秒内Service没有处理完成
这些事件必须要有输入事件的发生,如果没有的话,即使是主线程堵塞了,也不会发生ANR
如何分析
1、在log中可以看到输出的错误信息。获得ANR的类型。
2、可以去看应用进程和系统进程的函数堆栈信息。它们都输入到/data/data/traces.txt文件中。这个很关键
如何避免
1、避免在主线程做一些负责的耗时操作。比如网络数据发送、读写文件
2、BroadCast在处理复杂的数据的时候,在onReceive()方法中启动一个Service来处理
3、避免出现同步、死锁或者错误处理不恰当等情况