android沿用了Java的线程模型,一个Android应用在创建的时候会开启一个线程,即主线程(UI线程),其余的耗时活动(访问网络数据,计算,访问数据库)必须在子线程中完成,因为Android 3.0 以后,强制要求,否则会抛出异常,这是为了避免主线程被耗时操作阻塞导致ANR。(主线程被阻塞5s就ANR)
四、进程和线程的资源
堆栈
堆:
共有空间,是进程中最大的一块内存,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。对在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是如果不释放堆,会造成内存泄漏。主要用于存放新创建的对象。
栈
每个线程独有,分为虚拟机栈和本地方法栈,分别对应java和native部分,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈相互独立,因此栈是线程安全的。操作系统在切换线程的时候会自动切换栈。栈空间不用在高级语言显式的分配和释放。
程序计数器
每个线程独有的,为了保证线程切换以后能恢复到正确的执行位置。
字节码解释器通过程序计数器来依次读取指令,从而实现代码的流程控制,在多线程的情况下,程序计数器用于记录当前线程的执行位置,从而当当前线程被切换回来的时候能知道该线程上次执行到哪里了。
方法区
共有空间,主要存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
在操作系统级别上来看,主要是以下几个方面:
**更快的响应程序:**使用多线程可以减少程序的响应时间。如果某个线程很耗时,或者陷入上时间的等待,此时程序将不会响应鼠标和键盘等的操作,使用多线程以后可以把这个耗时操作分配到一个单独的线程去执行,从而使程序具备了更好的交互性。**开销小,提高资源利用率:**与进程相比,线程的创建和切换开销更小,同时多线程在数据共享方面效率十分高。**提高CPU利用率:**多CPU或者多个计算机本身就具有多线程的能力。如果使用单线程,将无法重复利用计算机资源,这会造成资源的巨大浪费。在多CPU计算机中使用多线程能提高CPU的利用率。简单的程序设计使用多线程能简化程序的结构,使程序便于理解和维护。**优化性能:**使用多线程可以设置优先级以优化性能。使用多线程的难点
等候使用共享资源时造成程序的运行速度变慢。这些共享资源主要是独占性的资源,如打印机。对线程进行额外管理要求额外的CPU开销。线程的使用会给系统带来上下文切换的额外负担。当这种负担超过一定限度,多线程的就得不偿失了。线程的死锁。不仅仅是死锁,主要是较长的等待或者资源竞争以及死锁等多线程现象。原子性的保持。因为多线程数据共享的特点,这是一个优点,同时也是一个难点,主要就是保证数据的原子性,不能出现脏读。 可以直接查看源码:
public enum State { /** * Thread state for a thread which has not yet started. */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }分为六个状态:
NEW: 新创建状态。线程被创建,但是还么有调用start方法,在线程运行之前还有一些基础工作要做。NEW这种状态对于每个线程来说,只可能有一次处于该状态,因为线程实例只能被启动一次。**Runnable:**可运行状态。一旦调用start方法,线程就处于runnable状态。一个可运行的线程可能处于运行状态,也可能没有运行,这取决于操作系统的调度。**Blocked:**阻塞状态。当线程申请一个由其他线程持有的独占资源(比如锁)时就会处于该状态。当线程不再阻塞时,状态会从BLOCKED转为RUNNABLE。Waiting:等待状态。线程暂时不活动,并且不运行任何代码,这是消耗最少的状态,等待线程调度器重新激活他。**Timed waiting:**超市等待激活。和等待状态不同的是,它可以在指定时间结束以后自行返回。**Terminated:**终止状态。当前线程执行完毕。无论是正常run方法执行完毕还是异常终止,都终止了。NEW到Runnable
Java刚创建出来的Thread对象就是NEW状态,不会被操作系统调度执行。从NEW到RUNNABLE状态调用start方法就行,这时候操作系统可以调度这个线程了。
Runnable到Blocked
是synchronized修饰的方法,代码同一时刻只允许一个线程持有,其余线程只能阻塞等待,等待的线程就会从Runnable到Blocked。
当等待的线程获得 synchronized 隐式锁时,就又会从 BLOCKED 转变到 RUNNABLE 状态。 在操作系统层面,线程是会转变到休眠状态的,但是在 JVM 层面,Java 线程的状态不会发生变化,即 Java 线程的状态会保持 RUNNABLE 状态。JVM 层面并不关心操作系统调度相关的状态,因为在 JVM 看来,等待 CPU 使用权(操作系统层面处于可执行状态)与等待 I/O(操作系统层面处于休眠状态)没有区别,都是在等待某个资源,都归入了 RUNNABLE 状态。
Runnable与Waiting的状态改变
获得 synchronized 隐式锁的线程,调用无参数的 Object.wait() 方法,状态会从 RUNNABLE 转变到 WAITING;调用 Object.notify()、Object.notifyAll() 方法,线程可能从 WAITING 转变到 RUNNABLE 状态。调用无参数的 Thread.join() 方法。join() 是一种线程同步方法,如有一线程对象 Thread t,当调用 t.join() 的时候,执行代码的线程的状态会从 RUNNABLE 转变到 WAITING,等待 thread t 执行完。当线程 t 执行完,等待它的线程会从 WAITING 状态转变到 RUNNABLE 状态。调用 LockSupport.park() 方法,线程的状态会从 RUNNABLE 转变到 WAITING;调用 LockSupport.unpark(Thread thread) 可唤醒目标线程,目标线程的状态又会从 WAITING 转变为 RUNNABLE 状态。RUNNABLE 与 TIMED_WAITING 的状态转变
Thread.sleep(long millis)
Object.wait(long timeout)
Thread.join(long millis)
LockSupport.parkNanos(Object blocker, long deadline)
LockSupport.parkUntil(long deadline)
TIMED_WAITING 和 WAITING 状态的区别,仅仅是调用的是超时参数的方法。
RUNNABLE 到 TERMINATED 状态
线程执行完 run() 方法后,会自动转变到 TERMINATED 状态执行 run() 方法时异常抛出,也会导致线程终止Thread类的 stop() 方法已经不建议使用