1、线程概念
线程:CPU能够运算调度的最小单位。(线程自己不拥有系统资源,与其它线程共享所在进程的资源)
进程:系统进行资源分配和调度的基本单位。
线程作用:减少并发执行任务的开销,提供系统的并发性能。
2、Android中的线程分类
2.1 主线程(UI线程)
定义:Android系统在程序启动时会自动启动一个线程,这个线程叫主线程。
作用:处理四大组件与用户交互事件。
注:因为用户随时会跟界面发生交互,主线程任何时刻都必须保持高速响应,所以在主线程中不允许做耗时操作,否则出现ANR。
2.2 子线程(工作线程)
定义:手动创建的线程
作用:可进行耗时操作(网络请求、I/O操作)
3、多线程
3.1多线程定义
多个线程同时执行多个任务
1)其实计算机任何时刻都只能执行一个任务;
2)多线程只是一种错觉,因为JVM快速调度资源来轮换线程,使得线程不断轮流执行,多以看起来好像多个任务同时进行。
3.2 Android多线程编程两大原则
1)不要在主线程做耗时操作,不然会阻塞主线程,阻塞超过5会报ANR;(主线程要快速响应用户动作,所以不能在主线程做耗时操作,否则会阻塞此线程,导致无法响应用户动作)
2)不要在主线程之外线程更新UI组件;(为了保证更新UI组件线程安全,所以必须在主线程更新)
即更新UI组件放在主线程,耗时操作放在子线程。
4、Android多线程实现方式
4.1 Java 线程
- 继承Thread类
- 实现Runnable接口
4.2 Android封装的线程类
- AsyncTask
定义:Android封装的轻量级异步类。
作用:一是实现多线程;二是异步通信和消息传递。
实现原理:线程池+Handler
优点:
1)方便实现异步通信;(不需要使用"任务线程+Hander方式")
2)节省资源(内部采用线程池,避免频繁创建和销毁线程带来的资源开销)
- HandlerThread
定义:Android封装的带Looper的Thread子类。
观察HandlerThread的官方文档的两句:①Thread. Handy class for starting a new thread that has a looper.②The looper can then be used to create handler classes.
释义:HandlerThread对象start后可以获得其Looper对象,并且使用这个Looper对象实例Handler,之后Handler就可以运行在其他线程中了。
作用:创建一个工作线程的Looper,并解决了创建Looper过程中同步问题。
定义:意图服务
原理:继承Service,使用了HandlerThread、Handler,利用Handler(Handler+Looper+MessageQueue)机制解决并发问题
使用场景:需后台执行耗时任务场景
5、各线程对比
6、Synchronized解决多线程并发问题
6.1 Synchronized作用
保证同一时刻最多只有1个线程执行被Synchronized修饰的方法/代码。
其他线程 必须等待当前线程执行完该方法 / 代码块后才能执行该方法 / 代码块
6.2 应用场景
保证线程安全,解决多线程中的并发同步问题(实现的是阻塞型并发),具体场景如下:
- 修饰 实例方法 / 代码块时,(同步)保护的是同一个对象方法的调用 & 当前实例对象
- 修饰 静态方法 / 代码块时,(同步)保护的是 静态方法的调用 & class 类对象
6.3 原理
1)依赖JVM实现同步
2)底层通过一个监听器(monitor)对象完成,wait()、notify()等方法也依赖于monitor对象
监视器锁(monitor)的本质 依赖于 底层操作系统的互斥锁(Mutex Lock)实现
6.4 锁的类型和区别
6.5 使用方式
/**
* 对象锁
*/
public class Test{
// 对象锁:形式1(方法锁)
public synchronized void Method1(){
System.out.println("我是对象锁也是方法锁");
try{
Thread.sleep(500);
} catch (InterruptedException e){
e.printStackTrace();
}
}
// 对象锁:形式2(代码块形式)
public void Method2(){
synchronized (this){
System.out.println("我是对象锁");
try{
Thread.sleep(500);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
/**
* 类锁
*/
public class Test{
// 类锁:形式1 :锁静态方法
public static synchronized void Method1(){
System.out.println("我是类锁一号");
try{
Thread.sleep(500);
} catch (InterruptedException e){
e.printStackTrace();
}
}
// 类锁:形式2 :锁静态代码块
public static void Method2(){
synchronized (Test.class){
System.out.println("我是类锁二号");
try{
Thread.sleep(500);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
Synchronized
修饰方法时存在缺陷:若修饰1个大的方法,将会大大影响效率.