多线程
1.多线程
1.1 程序、进程、线程
程序:一组命令的集合,为了完成指定的功能,程序时静态概念,一般保存在硬盘当中
进程:正在运行的程序,是一个动态概念,需要保存在内存当中,操作系统会分配对应的
PID,当我们直接关闭某个进程的时候,该进程会在运行内存中被销毁
线程:一个程序中,不同的执行分支,如果同一个时间节点允许多个线程同时执行时,
我们称为多线程
在Java中,main方法开始执行,就是一个线程,称为主线程
1.2 并行和并发
并行:多个CPU,同时执行多个任务
并发:一个CPU,同时执行多个任务
多线程并行 必须大于等于2 才行
单核CPU没有多线程
1.3 单核CPU和多核CPU
1.单核CPU是一种假的多线程,因为在一个时间单元内只能执行一个线程的任务
2.如果是多核,才能更好地发挥多线程的效率
3.一个Java应用程序java.exe,其中至少有三个线程:main()主线程,gc()垃圾回收
线程,异常处理线程。 当然如果发生异常,会影响主线程
1.4 多线程优缺点和应用场景
单个线程先后完成多个任务比多个线程完成用时更短
优点:1.提高应用程序相应。对图形化界面更有意义,增强用户体验。
2.提高计算机系统CPU的利用率
3.改善程序结构。将既长又复杂的进程分为多个线程,独立运行,有利于理解和修改
场景:程序需要同时执行多个任务
程序需要实现一些需要等待的任务时
需要一些后台运行的程序时
1.5 线程创建
1.5.1 Thread
第一种:创建一个类,继承Thread类 并覆写run方法
run方法等于是新线程中的main方法
public void run(){}
1.5.2 Runnable
第二种:创建一个类,实现Runnable接口,并覆写run方法
class Processor implements Runnable{}
//创建线程类对象
Thread t1 = new Processor();
//调用start方法,启动线程
t1.start();
1.5.3 继承和实现的区别
区别:
继承 Thread :线程代码存放Thread子类run方法中
实现 Runnable:线程代码存在接口的子类的run方法
实现方式的好处
避免了单继承的局限性
多个线程可以共享同一个接口实现类的对象,适合多个相同线程
来处理同一份资源
1.6 优先级和常用方法
1.6.1 优先级概述
进程的优先级等级
MAX_PRIORITY: 10
MIN_PRIORITY: 1
NORM_PRIORITY:5
涉及方法:
getPriority(): 返回线程优先值
setPriority(int newPriority):改变线程的优先级
说明:
线程创建时继承父线程的优先级
低优先级只是获得调度的概率低,并非一定是在高优先级线程之后被调用
1.6.2 常用方法
getName:获取线程的名字
setNaem:设置线程的名字,如果不设置,默认是Thread-0开始依次递增
setPriority():设置优先级,java中有1-10,10个优先等级
getPriority():获取优先级等级
static currentThread():获取当前线程对象
static sleep():让当前线程进入睡眠状态
currentThread:出现在哪个线程中,就获取哪个线程的对象
sleep:出现在哪个线程中,就睡眠哪个线程,参数为long类型的毫秒数
1.7 声明周期
新建、就绪、运行、阻塞、死亡
具体看笔记
1.8线程控制
图
1.8.1 线程停止
stop:终止某个线程执行,已过时,可能会导致死锁
1.8.2线程合并
join:让当前线程等待指定线程执行完再执行
t1.join(); //等待t1线程执行完再继续执行
1.8.3 Yield
yield:静态方法,暂停当前正在执行的线程对象,
并执行其他等待中的线程、
1 静态方法 意味着跟哪个对象调用没有关系,写在哪个线程中,哪个线程就让位
2 给同优先级让位,不同优先级不让位
1.9 线程同步
1.9.1 概述
当多个线程有可能同时操作同一个数据的时候,为了保证数据一致性,需要进行同步执行
本质是同步数据,一种安全机制
异步编程:线程之间是完全独立的,相互没有影响
同步编程:线程之间不是完全独立的,相互可能有影响
同步场景:
多个线程可能在同一时间对数据进行更改操作,查询无所谓
1.9.2 不同步带来的问题
详见笔记
1.9.3 解决方法
1.方法锁
synchronized是修饰符,如果加了那么该方法就只能有一个线程执行
2. 语句块锁
适用于只有部分代码需要同步
synchronized(this){}
1.9.4 synchronized
synchronized(对象){} 成员语句块锁
synchronized(类名.calss){} 静态语句块锁
当访问一个对象中加锁的成员方法或者成员语句块锁时,该对象中所有加锁的成员方法
和成员语句块锁全部锁定
当访问一个类中加锁的静态方法或者静态语句块锁时,该对象中所有……全部锁定
当前对象(相同数据)所有加锁的是相互排斥,不会同步进行
1.10 Lock
1.10.1 概述
同故宫显式定义同步锁对象来实现同步
每次只能有一个线程对Lock对象加锁,县城开始访问共享资源之前应先获得Lock对象
1.10.2 使用
//创建锁对象
Lock lock = new ReentrantLock();
public void withDraw(double money){
lock.lock(); //开始同步
lock,unlock(); //解锁
}
1.10.3 优缺点
是显示锁,需要手动开启关闭,synchronized是隐式锁,自动开启,执行完关闭
只有代码块锁,而synchronized支持方法和代码块锁
需要JVM花费较少的时间来进行资源调度,性能相对较好,有很好的扩展性
使用顺序:Lock锁 --> 同步代码块锁 --> 方法锁
1.11 定时器任务
1.11.1 概述
定时器:计划任务
只要有一个计划任务,就会开启一个线程,进行计时,到达指定时间后,由该线程来完成这个任务
1.11.2 使用
//1 要做的事,也就是任务对象
//2 什么时候开始做,1000*5,就是5秒后开始
//3 间隔时间,3秒
Timer t = new Timer();
t.schedule(new LogTimerTask(),1000*5,1000*3);