知识是什么,知识就是看完了书把书扔掉之后脑中那些清晰、准确、必要的概念。
之前也写了挺多关于线程的博客,但是由于自己基础不扎实,大多数都是摘录别人的东西。所以这篇文章就是对一些重要的概念进行总结,把知识归纳整理,这篇博客会长期更新,只要遇到了一些自己不懂而且重要的理论就会添加上去。
前台进程、可见进程、服务进程、后台进程、空进程
1、前台进程 (Foreground process)
一个正在与用户交互的Activity
进程持有一个Service,这个Service处于这几种状态:
①Service与用户正在交互的Activity绑定。
②Service是在前台运行的,即它调用了 startForeground()。
③Service正在执行它的生命周期回调函数(onCreate(), onStart(), or onDestroy())。
进程持有一个BroadcastReceiver,这个BroadcastReceiver正在执行它的 onReceive() 方法。
2、可见进程(Visible process)
进程持有一个Activity,这个Activity不在前台,但是仍然被用户可见(处于onPause()调用后又没有调用onStop()的状态,比如,前台的activity打开了一个对话框,这样activity就会在其后可见)。
进程持有一个Service,这个Service和一个可见的(或者前台的)Activity绑定。
3、服务进程 (Service process)
如果一个进程中运行着一个service,这个service是通过 startService() 开启的,并且不属于上面两种较高优先级的情况,这个进程就是一个服务进程。
在Service中新启动线程
上传一个图片文件,应该开启一个service来进行上传工作,这样在用户离开activity时工作仍在进行
4、后台进程 (Background process)
进程持有一个用户不可见的activity(activity的onStop()被调用,但是onDestroy()没有调用的状态),就认为进程是一个后台进程。
后台播放音乐,后台下载数据等
直接在Activity中新开一条线程来做耗时操作,当该Activity退出到桌面或其他情况
5、空进程
一个进程不包含任何活跃的应用组件
一个进程当中已经没有数据在运行了,但是内存当中还为这个应用驻留了一个进程空间
1、设置属性priority最高优先级,1000是最高值
2、在onStartCommand里面调用 startForeground()方法把Service提升为前台进程级别
3、onStartCommand方法,返回START_STICKY
public int onStartCommand(Intent intent, int flags, int startId) {
flags = START_STICKY;
returnsuper.onStartCommand(intent, flags, startId);
}
4、在onDestroy方法里发广播重启service
5、监听系统广播判断Service状态
6、将该进程设置为常驻内存进程:在AndroidManifest的Application中添加android:persistent=”true”
Thread、AsyncTask、HandlerThread、IntentService、ThreadExecutor
简单地开启一个子线程进行处理,比如说处理一张图片,读取资源文件,读写数据库等。
要手动控制开启和结束,不然会一直运行在后台,即使程序退出
适合与界面进行频繁交互,比如说进度条,也可以做Thread可以做的事
适合处理在前台的多线程串行的程序
适合处理在后台运行的,多线程串行程序
适合反复多次使用线程的程序,比如说音乐下载,图片加载(ImageLoader)
1、子线程创建Handler
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Handler handler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(Message msg) {
mTextView.setText("改变文字");
}
};
Looper.loop();
handler.sendEmptyMessage(123);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
1、执行并发操作代码:
loadImageAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, path);
submit内部调用execute
submit有返回值
submit方便exception处理
Callable中的call()方法类似Runnable的run()方法,就是前者有返回值,后者没有。
两者都是为那些实例可能被另一个线程执行的类设计的。
但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。
newFixedThreadPool 固定数量
newSingleThreadExecutor 串行
newCachedThreadPool 无限大
newScheduledThreadPool 固定数量,周期性执行
ArrayBlockingQueue:数组结构的阻塞队列
LinkedBlockingQueue:链表结构的阻塞队列
PriorityBlockingQueue:有优先级的阻塞队列
SynchronousQueue:不会存储元素的阻塞队列
AbortPolicy : 默认的实现,直接抛出一个RejectedExecutionException异常,让调用者自己处理。
DiscardPolicy : 如果队列满了,后续的任务都抛弃掉。
DiscardOldestPolicy : 将等待队列里最旧的任务踢走,让新任务得以执行。
CallerRunsPolicy : 既不抛弃新任务,也不抛弃旧任务,而是直接在当前线程运行这个任务。
每当线程池需要创建一个新线程,都是通过线程工厂获取。如果不为ThreadPoolExecutor设定一个线程工厂,就会使用默认的defaultThreadFactory
平时打印线程池里线程的name时,会输出形如pool-1-thread-1之类的名称,就是在这里设置的。这个默认的线程工厂,创建的线程是普通的非守护线程,如果需要定制,实现ThreadFactory后传给ThreadPoolExecutor即可。