一.线程基础
含义:线程指代码的一套执行顺序(如 main是主线程)
完整功能的实现通常需要多个线程一起执行。
线程的创建(含代码实现)
方法本身没有绝对的优劣之分,而是根据任务需要进行选择。
方法一、继承Tread类
步骤一:子类继承Thread线程类
步骤二:重写继承Thread类的run方法---->此线程方法的执行体
步骤三:创建继承Thread类的对象,并以此代表一个新线程
步骤四:通过start方法启动线程(自动执行重写的run方法)
缺点及注意!!!
不足:由于子类已经继承Thread线程类(已经有一个父类),无法再继承其他类,因此不利于功能的扩展。
注意:
1.此处新的线程必须放在main线程执行体的前面,否则main线程会执行完毕后再执行其他的线程。(不符合线程一起执行的要求)
2.若启动线程误将start方法错用为run方法,则只会执行main线程,而不会执行其余线程。
方法二、实现Runnable接口
步骤一:创建实现类,实现Runnable接口
步骤二:重写Runnable接口的run()方法 ---->此线程方法的执行体
步骤三:创建任务对象
步骤四:把任务对象交给线程对象(Thread)处理
优缺点及注意!!!
优点:与实现类相关,可以实现更多的接口,继承其他的类,扩展性更强(即利于丰富实现功能)
缺点:需要多创建一个Runnable实现对象
注意:代码仍需要放到main执行体之前(如方法一)
方法三、实现Callable接口
步骤一:创建实现类,实现Callable接口
步骤二:重新接口中的call方法,作为新线程的执行体
步骤三:创建Callable对象,并将其封装成一个FutherTask(任务对象)
步骤四:将任务对象交给Thread对象,并start执行
步骤五:执行完毕后返回(或获取)相关值(根据需要,在实现类中规定)----通过get()
优缺点及注意!!!
优点:只是实现接口,可以继承类和实现其他接口,扩展性强;线程结束后,可以获取执行结果;
缺点:显而易见----代码比较复杂!!!
补充:FutherTask(未来任务)
它是一个任务对象 && 在线程结束完毕后,通过get()方法获取返回值
线程创建后的常用方法
如图所示: ---> 大家可以去idea模拟一下
二、线程进阶
线程安全问题
解释:多个线程同时操作一个共享资源的时候,可能会出现业务安全问题。(eg:两人同时取10万元,但银行卡只有十万元)
线程安全问题的解决方案---线程同步
线程同步:让多个线程实现先后依次访问共享资源,这样就解决了安全问题(通俗解释:上厕所依次进入,里面的人出去才开门允许下一个人进入)
方法一、同步代码块
含义及运行:把核心代码块(线程的执行体)使用时上锁,依次保护线程安全。
注意:同步锁必须是同一对象,否则会出bug
方法二、同步方法
其实就是将synchronized关键词加到方法上。
原理:其底层也是有隐式锁,只是锁的范围是整个代码。
注意!!!
如果该方法是实例方法,是this作为锁对象; 如果是静态方法,默认是类名.class作为锁对象。
线程池
一个可以复用线程的技术(线程可以反复使用)
处理Runnable 和 Callable 任务
拖住几个核心线程 -- 创建临时线程 ---之后再拒绝处理任务(当前很多任务都没处理)。
线程的配置:
//核心线程数量怎么配置
计算密集型任务:核心线程数量=cpu核数 +1
I0密集型的任务:= cpu核数 + 2
并发与并行:
CPU轮番为系统的每个线程服务,就是并发。
在同一时刻上,同时有多个线程在被CPU调度执行,就是并行。
进程表示程序运行(有多个线程在执行)