1.概念
进程:正在运行的程序,也就是说,一个程序进入内存运行,即变成一个进程,进程是运行过程中的程序,并具有一定独立的功能
线程:线程是进程中的一个执行单元,负责当前进程中的程序的运行,一个进程中至少有一个线程。一个进程是可以有多个线程的,这个应用程序也可以称之为多线程程序
一个程序运行后至少包含一个进程,一个进程中可以包含多个线程
多线程:一个程序中有多个线程在同时执行
单线程程序:若有多个任务只能依次执行,当上一个任务执行任务结束后,下一个任务才开始执行
单线程程序:若有多个任务可以同时执行
2.程序运行原理
分时调度:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间
抢暂式调度:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度
3.主线程
jvm启动后,必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程
4.Thread类
Thread是程序中的执行线程
构造方法:Thread()分配新的Thread对象
Thread(String name)分配新的Thread对象,并指定name作为其线程名称
常用方法:start() 该线程开始执行,java虚拟机开始调用该线程的run()方法
run() 该线程要执行的操作
sleep(long millis) 在指定的毫秒数之内让当前正在执行的线程休眠(暂停执行)
5.创建线程的方式
(1)继承Thread类
创建线程的步骤:定义一个类继承Thread
重写run方法
创建子类对象,就是创建线程对象
调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法实现多个线程的执行
线程对象调用 run方法和调用start方法区别?
调用run方法不开启线程,只是对象调用方法,调用start开启线程,并让jvm调用run方法在开启的线程中执行
创建线程的目的:为了建立程序单独的执行路径,让多部分代码同时执行,也就是说线程创建并执行需要给定线程要执行的任务
主线程的任务是定义在main方法中的,自定义线程需要执行的任务都定义在run方法中,也就是重写run方法
多线程程序执行具有随机性
结果:
获取线程名称的方法
Thread.currentThread().getName();获取当前线程对象的名称
(2)创建线程方式—实现Runnable接口
步骤:
创建线程任务类 实现Runnable接口
在线程任务类中 重写接口中的run方法
创建线程任务类对象
创建线程对象,把线程任务类对象作为Thread类构造方法的参数使用
调用start方法,启动线程,通过JVM,调用线程任务类中的run方法
(3)实现Callable接口方式
使用线程池方式—Callable接口
Callable接口:与Runnable接口功能相似,用来指定线程的任务。其中的call()方法,用来返回线程任务执行完毕后的结果,call方法可抛出异常
实现步骤:
创建线程池对象 Executors.newFixedThreadPool(int 个数)
线程池对象ExecutorService接口实现类,调用submit(task)提交线程任务
submit(Callable c)
6.线程池
线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源
7.多线程的异步计算
计算1加到100的和,1+200的和
8.线程同步(线程安全处理Synchronized)
线程同步的方式有两种:
方式1:同步代码块
方式2:同步方法
同步代码块
synchronized (锁对象) {
可能会产生线程安全问题的代码
}
同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全
同步方法
同步方法:在方法声明上加上synchronized
public synchronized void method(){
可能会产生线程安全问题的代码
}
9.死锁
同步锁使用的弊端:当线程任务中出现了多个同步(多个锁)时,如果同步中嵌套了其他的同步。这时容易引发一种现象:程序出现无限等待,这种现象我们称为死锁。这种情况能避免就避免掉
synchronzied(A锁){
synchronized(B锁){
}
}
10.Lock接口
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作
Lock接口中的常用方法:
lock() 获取锁
unlock()释放锁
11.等待唤醒机制
在开始讲解等待唤醒机制之前,有必要搞清一个概念——线程之间的通信:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制。
等待唤醒机制所涉及到的方法:
wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。
notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。
notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。
sleep()和wait()方法的区别
sleep: 不释放锁对象, 释放CPU使用权
在休眠的时间内,不能唤醒
wait(): 释放锁对象, 释放CPU使用权
在等待的时间内,能唤醒
为什么wait(),notify(),notifyAll()等方法都定义在Object类中
锁对象可以是任意类型的对象