一个基本的CPU执行单元 & 程序执行流的最小单元,比进程更小的可独立运行的基本单位,可理解为:轻量级进程
组成:线程ID + 程序计数器 + 寄存器集合 + 堆栈
注:线程自己不拥有系统资源,与其他线程共享进程所拥有的全部资源。
减少程序在并发执行时所付出的时空开销,提高操作系统的并发性能。
为什么有了线程还要有进程?
进程的缺陷:
进程属于在处理器这一层上提供的抽象;线程则属于在进程这个层次上再提供了一层并发的抽象。线程用于提高进程的并发度。
进程和线程的主要差别在于它们是不同的操作系统资源管理方式:
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
线程是进程的一个实体, 是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。
4.1)守护线程
守护用户线程的线程,即在程序运行时为其他线程提供一种通用服务,如垃圾回收线程
//设置该线程为守护线程
thread.setDaemon(true);
4.2)非守护线程(用户线程)
a.主线程(UI线程)
Android系统在程序启动时会自动启动一条主线程,用于处理四大组件与用户进行交互的事情(如UI、界面交互相关)
注:因为用户随时会与界面发生交互,因此主线程任何时候都必须保持很高的响应速度,所以主线程不允许进行耗时操作,否则会出现ANR
b.子线程(工作线程)
用户手动创建的线程,用于处理耗时的操作(网络请求、I/O操作等)
4.3)守护线程 & 非守护线程的区别
区别:虚拟机是否已退出:
当所有用户线程结束时,因为没有守护的必要,所以守护线程也会终止,虚拟机也同样退出;反过来,只要任何用户线程还在运行,守护线程就不会终止,虚拟机就不会退出。守护线程不属于不可或缺的存在。
5.1)表示
线程优先级分为10个级别,分别用Thread类常量表示。
Thread.MIN_PRIORITY // 优先级1
Thread.MAX_PRIORITY // 优先级10
5.2)设置
通过方法setPriority(int grade)进行优先级设置
默认线程优先级是5,即 Thread.NORM_PRIORITY
多线程
一个程序(进程)运行时产生多个线程(任务)同时进行。
多线程目的
提高CPU资源的利用率,包括以下三点:
并行与并发
并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。
其实,多线程本质是并发执行程序。因为计算机任何特定时刻只能执行一个任务;多线程只是一种错觉:只是因为JVM快速调度资源来轮换线程,使得线程不断轮流执行,所以看起来好像在同时执行多个任务而已(异步执行)
线程安全
一段代码是线程安全的是指:在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果。这个时候使用多线程,我们只需要关注系统的内存,cpu是不是够用即可。反过来,线程不安全就意味着线程的调度顺序会影响最终结果,如不加事务的转账代码:
void transferMoney(User from, User to, float amount){
to.setMoney(to.getBalance() + amount);
from.setMoney(from.getBalance() - amount);
}
如果线程不安全,则程序执行的结果并不是我们想要的结果,甚至有可能会导致实际场景严重的安全问题。
同步与异步
同步:发送一个请求,等待返回,然后再发送下一个请求;同步可以避免出现死锁,读脏数据的发生,可以保证安全性。
异步:发送一个请求,不等待返回,随时可以再发送下一个请求;异步则是可以提高效率,可以并发执行多项工作。
Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。如上面的代码简单加入@synchronized关键字。
(1)多线程编程两大原则
1、不要阻塞UI线程(即主线程):单线程会导致主线程阻塞,然后出现ANR错误:主线程被阻塞超过5s则会出现错误
2、不要在UI线程之外更新UI组件
(2)解决方案——1个主线程+n个工作线程
1、将耗时任务放在工作线程中执行
2、将更新UI组件放在主线程中执行
(1)调度方式
1、当系统存在大量线程时,系统会通过时间片轮转的方式调度线程,因此线程不可能做到绝对的并发
2、处于就绪状态(Runnable)的线程都会进入到线程队列中等待CPU资源(同一时刻在线程队列中可能有很多个)
3、在采用时间片的系统中,每个线程都有机会获得CPU的资源以便进行自身的线程操作;当线程使用CPU资源的时间到后,即时线程没有完成自己的全部操作,JVM也会中断当前线程的执行,把CPU资源的使用权切换给下一个队列中等待的线程。(被中断的线程将等待CPU资源的下一次轮回,然后从中断处继续执行)
(2)调度优先级
Java虚拟机(JVM)中的线程调度器负责管理线程,并根据以下规则进行调度:
1、根据线程优先级(高-低),将CPU资源分配给各线程
2、具备相同优先级的线程以轮流的方式获取CPU资源
1、定义
当线程A使用同步方法A时,其他线程必须等到线程A使用完同步方法A后才能使用
2、同步方法用关键字 Synchronized 进行修饰
public synchronized void Sb_Android(){
}
3、死锁
(3.1)死锁的四个必要条件
(3.2)死锁的处理方法
(3.3)鸵鸟策略
把头埋在沙子里,假装根本没发生问题。
因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。
大多数操作系统,包括 Unix,Linux 和 Windows,处理死锁问题的办法仅仅是忽略它。
(3.4)死锁的检测与死锁恢复
(3.5)死锁的预防
在程序运行之前预防发生死锁。
(3.6)死锁的避免
线程A在占有CPU资源期间,通过调用join()方法中断自身线程执行,然后运行联合它的线程B,直到线程B执行完毕后线程A再重新排队等待CPU资源,这个过程称为线程A联合线程B
是进程实体的运行过程 & 系统进行资源分配和调度的一个独立单位
使多个程序可 并发执行,以提高系统的资源利用率和吞吐量