学习线程都要搞清楚这几个问题
1 进程与线程的区别
一个进程,可以有N个线程。一个android app,一般是一个进程,设置android:process例外。
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
2 线程的几种常见方法
- new Thread
- runnable
- callable : 这种可以返回
- 线程池创建线程
3 线程有哪几种状态?
五种状态:创建new,阻塞block,就绪ready,运行run,死亡dead
new Thread() | 创建new |
---|---|
thread.start() | 就绪ready |
Thread.sleep() | 当前Thread阻塞block |
joint() | 阻塞block |
yield() | 就绪状态ready |
run执行完了 | 死亡dead |
wait | 当前Thread阻塞block,需要唤醒进行获取锁的队列 |
4 线程的sleep和yield方法有什么区别?
sleep 阻塞时,cpu时间让给其他线程,对线程无优先级的要求。进入阻塞状态。不依赖OS
yield 阻塞时,cpu让给优先级高的线程。进入就绪状态。效果依赖操作系统
5 wait和notify方法的作用,为什么他们会被放入object类,而不是thread类?
sleep,用线程.sleep调用。而wait,notify,notifyall,都是用线程持有的锁,锁.wait, 锁.notify来调用。要加同步代码块。
wait,让获得锁的线程释放锁,并把线程放入等待获取锁的队列中。
notify,从等待获取锁的队列中,取出一个线程,获得锁。
原因有两个
- 每个对象都可以作为锁。object是对象的基类,方法放在这里易于操作。
- 一个线程可以有多个对象锁。wait和nofity有一个对应关系,放在线程里,绝对会乱。只能放在对象里。
6 多线程面临的问题有哪些?
多线程,是轮流获取cpu的时间,但共享所属进程的内存。
多线程,快,但是也带来了并发。对内存,数据库等资源的读写不同步的问题。
使用同步块,锁,等等机制可以解决。
多线程上下文切换,会消耗更多的资源。
无法保证线程执行的顺序性
7 如何保证线程ABC顺序执行?
线程ABC已经new了,
A.start();
A.join();
B.start();
B.join();
C.start();
A.join是调用了A对象的wait方法。让主线程失去了A的对象锁,进入了,A对象的等待锁队列。此时,后面的线程不能执行,已经在running的A则不受影响。
8 线程池有哪几种?什么情况下使用?
四种线程池。
单例线程池 | SingleThreadExcutor | 一个核心 | 顺序执行 |
---|---|---|---|
定长线程池 | FixedThreadPools | 固定个数核心 | 略 |
缓存线程池 | CachedThreadPools | 全是非核心 | 无空闲线程,则new,有,则复用。空闲一定时间后回收 |
调度线程池 | SchuledThreadPools | 几个数核心,其他非核心 | 用作延后及定时任务,取代timer,timetask |
9 wait和sleep有阻塞线程执行的作用,有什么区别?
wait,执行后回丢锁,回到block状态,需要获取锁,才能进入就绪状态。
sleep,不丢锁,回到block状态,时间到了,就进入就绪状态。
都是进入block状态,wait进入等待锁的池子,sleep不需要。
====
10 多线程之间的协同是如何进行的?
wait,notify,nofityall
11 多线程之间是如何通讯的?
handler,looper,messageQueue
只有获取了handler,才能发message
message只能发到messageQueue
looper取出message执行