线程构造方法:
- 设置线程名
- 线程的任务
- 设置线程分组
线程的常用属性:
ID,Name…状态
优先级(1-10 默认5)
守护线程(后台线程)
守护线程注意:
1.在守护线程里面创建的线程,默认是守护线程
2.守护线程状态的设置必须放在线程启动之前
start和run方法的区别
run属于普通方法,start是启动线程的方法
run方法可以执行多次,start方法只能执行一次
线程中断:
使用全局自定义的变量来终止线程-------------------->收到终止指令后,会执行完当前任务再终止
使用线程提供的终止方法 interrupt 来终止线程---->收到终止指令之后,立马终止
使用线程提供的方法 stop 来终止线程(弃用,终止之后,未释放资源,有安全隐患)
终止线程
Thread.interrupted()方法,判断完线程状态之后,就会将线程状态设置为false;
Thread.currentThread.isInterrupted()方法,执行判断线程终止为true之后,
等待一个线程
join()
获取当前线程引用
currentThread()
线程状态
NEW------------------->新建状态,没有调用start()之前的状态
RUNNABLE---------->运行状态,(running执行中,ready就绪(等待cpu时间片))
BLOCKED------------>阻塞状态,多个线程试图获得同一把锁
WAITING-------------->等待状态,没有明确的等待结束时间,调用wait()
TIMED_WAITING—>超时等待状态,有明确的等待时间,如:sleep(xxx)
TERMINATED-------->终止状态
yield()
出让CPU执行权,特点:不一定能成功出让cpu执行权
线程安全
线程不安全:多线程执行中,程序的执行结果和预期的不相符,就叫做线程不安全
线程非安全:
- cpu抢占式执行(万恶之源)
- 非原子性
- 编译器优化(代码优化)编译器优化在单线程下没问题,可以提升程序的执行效率,但是在多线程下就会出现混乱,导致线程不安全问题(指令重排序)
- 内存不可见
- 多个线程修改了同一个变量
volatile 关键字(轻量级解决“线程安全”)
解决问题:
- 强制内存可见(原理:当操作完变量之后,强制删除线程工作内存中的此变量)
- 禁止指令重排序
注意:
volatile不能解决原子性问题
解决线程安全:
- CPU抢占调度(不能解决)
- 每个线程操作自己的变量(可能解决)
- 在关键代码上让所有CPU排队执行,加锁;
加锁操作的关键步骤
- 尝试获取 (如果成功拿到锁,加锁,没拿到就等待)
- 释放锁
Java中解决线程安全问题的方案:
- synchronized 加锁和释放锁(JVM层面的解决方案,自动进行加锁释放锁)
- Lock 手动锁【程序员自己加锁,释放锁】
Synchronized注意事项:
在进行加锁操作的时候,同一组业务一定是同一个锁对象;
synchronized实现原理:
- 从操作来看:互斥锁实现 mutex lock
- JVM:monitorenter–>monitorexit实现了监视器的加锁和释放锁的操作
- Java:
a)锁对象:mutex
b)锁存放的地方:加锁对象的头信息
Lock
注意:一定要把lock()放在try外面
1.如果将lock()方法放在try里面,那么try里面的代码出现异常之后,就会执行finally里的释放锁代码,但还没加锁成功
2.如果将lock()方法放在try里面,那么执行finally的释放锁代码时报的异常就会覆盖try里面的异常
synchronized锁机制是非公平锁
公平锁可以按顺序进行执行,而非公平锁执行的效率更高,是抢占式的
在Java中所有锁默认的策略都是非公平锁
不释放锁会造成死锁
synchronized使用场景:
- 修饰代码块(加锁对象自定义)
- 修饰静态方法(加锁对象是当前类对象)
- 修饰普通方法(加锁对象是当前类的实例)
Lock只能修饰代码块
问题:
volatile和synchronized有什么区别
volatile可以解决内存可见性问题和禁止指令重排序,但volatile不能解决原子性问题
synchronized是用来保障线程安全的,也就是说synchronized可以解决任何关于线程安全的问题(5个:抢占式执行,原子性,编译器优化,内存不可见,多个线程修改同一变量)(关键代码排队执行,始终只有一个线程会执行加锁操作)
synchronized和Lock的区别
synchronized既可以修饰代码块,和静态方法或普通方法,lock只能修饰代码块
synchronized只有非公平锁策略,而lock既可以是公平锁,也可以是非公平锁(ReentrantLock默认是非公平锁,也可以通过构造函数声明它为公平锁)
ReentrantLock更加的灵活(如:tryLock)
synchronized是自动加锁释放锁,而RenntrantLock需手动加锁释放锁