多线程
本节课目标:
1.理解线程的概念
2.掌握线程的基本创建和启动方式
3.了解线程的几种常用方法
4.掌握线程调度的常用方法
5.掌握线程的同步
6.理解线程安全的类型
进程:它是应用程序的执行实例,它有独立的内存空间和系统资源。
应用程序的执行实例---->进程<----有独立的内存空间和系统资源
CPU调度和分派的基本单位---->线程<----进程中执行运算的最小单位,可完成一个独立的顺序控制流程
1.1.什么是多线程?
线程是CPU调度和分派的基本单位,它是进程中执行运算的最小单位,也是进程中运算的基本单位,一个线程可完成一个独立的顺序控制流程。
如果在一个进程中同时运行了多个线程,用来完成多个不同的工作,则称之为“多线程”。
多线程和单线程
单线程:如果一个程序中只有一个线程,则称为单线程。
多个线程交替占用CPU资源,而非真正的并非执行。
多线程和单线程的区别
(1)多线程在执行中并不一定有单线程执行快。
(2)多线程产生的根本原因也是他最根本的优势在于我们能够在一个程序中,同时干多件事。可以充分利用CPU资源。
(3)其实多线程有两个概念:一种是指单核CPU的多线程,一种是指多核CPU的多线程。
单核CPU:同时只能执行一个线程,但是同样可以实现多线程,这个多线程是抢占式/交替式执行的。
多核CPU:可以进行交替执行,也可以实现真正的物理上的并行执行。
1.2主线程
JAVA给我们准备了一个类,用来支持我们进行多线程编程,Thread类
java.lang.Thread类
在java中有且只有一个主线程,就是我们程序的入口main方法。
主线程
(1)main()方法即为主线程入口
(2)产生其他子线程的线程
(3)必须最后完成执行,因为他执行各种关闭动作
1.3线程的基本创建和启动
创建线程的两种方式
(1)继承java.lang.Thread类
(2)实现java.lang.runnable接口
使用线程的步骤:
定义线程 -> 创建线程对象 -> 启动线程 -> 终止线程
start()和run()的区别
如果是死奥用run()方法。他只是一个普通方法,届时将只有主线程在执行此方法而已。
如果是调用该start()方法,他将会开启一个线程,然后此线程将会和其他线程交替执行某些任务,此线程执行的内容就是run()方法内的任务。
1.3.1继承Thread类
线程创建的第一种方式:
(1)定义MyThread类继承Thread类
(2)重写run()方法,编写线程执行体
(3)创建线程对象,调用start()方法启动线程
第二种方法:
(1)实现runnable接口
(2)重写run()方法
(3)创建线程对象,组装runnable接口的实现类,
如果再创建第二个线程,这时候我们同样给其启动,会发现两个线程是交替执行的,并且没有什么规律。这种叫做“CPU的抢占式调度”。
多个线程交替执行,不是真正的并行。
线程每次执行时长由分配的CPU时间长度决定
启动线程是否可以直接调用run()方法;
如果线程不调用start()那么不会开启线程,直接使用线程调用run()方法会是主线程去调用run()方法。那么自然不会再出现交替执行,只有这一条main线程执行路径,属于单线程执行模式。
多线程的好处:
(1)充分利用CPU的资源
(2)简化编程模型
(3)带来良好的用户体验
1.4线程的生命周期
1.5了解线程的几种状态
创建状态:当new Thread()时,线程处于创建状态
就绪状态:当调用了start()之后,线程处于就绪状态
运行状态:当线程被分配到CPU资源,线程处于运行状态,
如果线程运行状态时,是处于抢占执行的,当没抢到时又回到就绪状态。
死亡状态:当线程执行完任务,或者被外部干涉结束,线程会进入死亡状态
阻塞状态:当用户在输入/线程在休眠时,线程会进入阻塞状态
1.6线程的调度
1.6.1线程优先级
代码演示:
1.7掌握线程的同步问题(线程安全)
同时有多个线程在执行任务,虽然他们是交替执行,但是速度切换很快,如果有一些资源被共享,可能会导致资源出错。
线程并发
可以通过加锁来解决安全问题。
synchronized同步
同步方法:
public synchronized void saleticket(){
}
同步代码块:
synchronized(this){
}
线程安全类型
StringBuffer和StringBuilder
它们在使用中没有区别,但是StringBuffer是线程安全的,而StringBuilder非线程安全,效果较高。
HashMap和Hashtable
Hashtable是线程安全的
ArrayList和Vector
Vector是线程安全的