第七章 多线程 ——Java
一、进程
1.什么是进程:
继承是程序的一次动态执行过程,他对应了从代码加载、执行至完成的一个完整过程,这个过程也是程序本身从产生、发展至消亡的过程。
操作系统同时管理一个计算机系统中的多个进程,让计算机系统中的多个进程轮流使用CPU资源,或者共享操作系统的其他资源。
2.进程的特点:
-
继承是系统运行程序的基本单位。
-
每一个进程都有自己独立的一块内存空间,一组系统资源。
-
每一个进程的内部数据和状态都是完全独立的。
二、线程
1.什么是线程:
线程是进程中执行运算的最小单位,可完成一个独立的顺序控制流程。每个进程中,必须至少建立一个线程(这个线程成为主线程)来作为这个程序的入口点。
如果在一个进程中同时运行多个线程来完成不同的工作,称之为“多线程”。 是多个线程共享相同的地址空间并且共同分享同一个进程 ,这些进程可以在操作系统的管理下并发执行。
三、多线程
1.什么是多线程
- 充分利用CPU资源:执行单线程程序时,若程序发生阻塞,CPU可能会处于空闲状态,这将会造成计算机资源浪费,而使用多线程可以在某个线程处理休眠或阻塞状态时运行其他线程,这样大大提高了资源利用率。
- 简化编程模型:一个即长又复杂的进程可以分为多个线程,成为几个独立的运行部分,如果写成单线程程序可能需要多重循环判断,而如果使用多线程控制,每个线程仅需要实现简单的流程,简化了程序逻辑。
- 带来良好的用户体验:由于多个线程可以交替执行,减少避免了因程序阻塞或意外情况造成的响应过慢现象。
2.如何实现多线程
用 Thread 类 Thread 类支持多线程
构造方法 | 说明 |
---|---|
Thread() | 分配新的 Thread() 对象 |
Thread(Runnable targe) | 分配新的 Thread() 对象, target 为 run() 方法被调用的对象 |
Thread(Runnable targe,String name) | 分配新的 Thread() 对象, target 为 run() 方法被调用的对象,name 作为新线程的名称 |
void run() | 执行任务操作的方法 |
void start() | 使线程开始执行,Java虚拟机代用该线程的 run() 方法 |
void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行) |
String getName() | 返回线程的名称 |
int getPriorty() | 返回线程的优先级 |
void setPriority(int newPriority) | 更改线程的优先级 |
static Thread currentThread() | 返回当前正在执行的线程对象的引用 |
boolean isAlive() | 测速线程是否属于活动状态 |
void join() | 等待该线程终止 |
void interrupt | 中断线程 |
void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
3.主线程
每个进程至少有一个主线程。他是从程序开始的时候开始执行的。
- 他是产生其他子线程的线程
- 通常它必须最后完成执行,因为它执行各种关闭动作
-
如何使用线程
-
定义一个线程,同时指明这个线程所要执行的代码,即期望完成的功能
-
创建线程对象
创建线程类两种方法,一种是继承 Thread 类,另一种是实现 Runnable 接口。
- 继承 Thread 类创建线程
- 需要重写 Thread 类并重写 Thread 类的 run() 方法。因为 Thread 类的 run() 方法是线程要执行操作任务,所以线程要执行的操作代码都要写在 run() 方法中,并通过调用 start() 方法启动线程后调用。
- 实现 Runnable 接口创建线程
- Runnable 接口定义在 java.lang 包中,其中声明了一个抽象方法 run() ,即 public void run() ,一个类可以同实现 Runnable 接口并实现其 run() 方法完成线程的活动,已实现的 run() 方法成为该线程的线程体。任何实现 Runnable 接口的对象都可以作为一个线程的目标对象。
-
启动线程
-
终止线程
-
-
线程状态
如何线程都具有五种状态,即创建,就绪,运行,阻塞,死亡状态。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jccHzFi-1622615103198)(img\线程的状态.png)]
-
创建状态
- 在程序中用构造方法创建了一个线程对象后,新的线程对象就处于创建状态,此时,他已经获取了相应的资源,但还没有处于可运行的状态,这时可以通过 Thread 类的方法来设置线程对象的属性。如线程名,设置线程的优先级等。 -
就绪状态
- 线程创建玩之后,就可以通过调用 start() 方法启动线程,即进入就绪状态,此时,线程将进入线程队列排队,等待CPU资源,这表明他已经具备了运行条件,在未获得CPU资源时,仍然不能真正执行。
-
运行状态
- 当就绪状态的线程获得CPU资源时,即可转入运行状态,执行 run() 方法。对只有一个CPU的计算机而言,任何时空只能有一个处于运行状态的线程占用CPU,即获得CPU资源。
-
阻塞状态
-
一个正在运行的线程因某种原因不能继续运行时,进入阻塞庄园。阻塞状态时一种“不可运行”的状态,而处于这种状态的线程在得到一个特定的事件后转回可运行状态。
-
可能使线程暂停执行的条件如下:
- 由于线程的优先级比较低,因此他不能获得CPU资源。
- 使用 slept() 方法使线程休眠
- 通过调用 wait() 方法,使线程等待
- 通过调用 yield() 线程显式让出CPU控制权。
- 线程由于等待一个文件,I/O事件被阻塞
- 死亡状态
- 一个线程的 run() 方法运行完毕,线程则进入死亡状态,处于死亡状态的线程不具有继续运行的能力。
-
-
4.线程的优先级
懂同一时刻有一个或得个线程处于可运行状态时,他们需要排队等待CPU资源,每个线程会自动获得一个线程的优先级,优先级的高低反映线程的重要或紧急程度。
线程的优先级用1~10表示,1表示优先级最低,10表示优先级最高,默认值是5。
5. 线程的休眠
在程序程序组允许一个线程进行短暂休眠,直接调用 Thread.sleep() 方法即可实现线程的休眠
sleep() 方法会让当前线程休眠(停止执行)mills毫秒,线程由运行中的状态进入不可运行状态,睡眠时间过后会再次进入就绪状态,需要判断他是否死亡 需要处理 InterruptedException 异常。
5. 线程的强制运行
join() 方法使当前的线程暂停执行,等待调用该方法的线程结束后再继续执行本线程。它有三个重载方法
public final void join()
public final void join(long mills)
public final void join(long mills,int nanos)
需要判断他是否死亡 需要处理 InterruptedException 异常。
6.线程的礼让
yield() 方法可以暂停当前的线程执行,允许其他线程具有相同优先级的线程获得运行机会,该线程仍处于就绪状态,不转为阻塞状态,此时相同现在其他相同或更高优先级的线程执行,如无其他相同或更高优先级的线程,则该线程继续执行。
7.线程的同步
有一些同时运行的线程需要共享数据,此时就需要考虑其他线程的状态和行为,否则不能保证程序运行结果的准确性。
如何实现:
一个线程类如果是通过实现 Runnable 接口实现的,那么类中的属性有可能被多个该类的线程对象共享,就有可能引发线程不同步的问题。
采用线程同步有两种方式
-
同步方法
使用 synchronized 修饰的方法控制对类成员的访问。每个类实例对应一把锁,方法一旦执行,就独占该锁。直到从该方法返回时才将锁释放,从此以后被阻塞的线程方能获得该锁,重新进入可执行状态。//通过哎方法声明中加入synchronized关键字来声明同步方法 访问修饰符 synchronized 返回值类型 方法名 (参数列表){//省略方法体。。。。。。} 或者 synchronized 访问修饰符 返回值类型 方法名 (参数列表){//省略方法体。。。。。。}
在语法中:
synchronized 是同步关键词。
访问修饰符是指 public , private 等。
-
同步代码块
代码块即使用{}括起来的一段代码,使用 synchronized 关键字修饰的代码块,成为同步代码块。
synchronized (syncObject){ //需要同步的代码 }
synchronized 块中的代码必须获得对象 syncObject 的锁才能执行,具体机制和代码同步一致。可以制定上锁的对象。
-
常见类型对比
-
Hashtable && HashMap
-
Hashtable
1. 继承 关系
实现了Map接口,Hashtable继承Dictionary类
2. 线程安全,效率较低
3. 键和值都不允许为null
-
HashMap
- 继承关系
实现了Map接口,继承AbstractMap类
-
非线程安全,效率较高
-
键和值都允许为null
-
-
StringBuffer && StringBuilder
前者线程安全,后者非线程安全
四、总结
-
2. 非线程安全,效率较高
3. 键和值都允许为**null**
-
StringBuffer && StringBuilder
前者线程安全,后者非线程安全