关于多线程学习
什么叫线程同步
线程同步即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程处于等待状态。
Thread类实现多线程
- 继承extend Thread 自定义线程继承Thread类
- 重写run方法,编写线程执行体
- 创建线程对象,调用start方法启动线程
- 调用start方法同时执行两个线程
- 线程开启不一定立即执行,由cpu调度执行
Runable接口实现多线程(用的最多)
- 实例类通过implements 继承接口
- 在类中(ctrl+o,alt+fn+ins)重写run方法
- 创建这个类的对象,通过new thread().start();启动
Callable接口用的最少
函数式接口
一个接口里面只包括一个抽象方法。
alt +enter创建方法。
线程停止
建议使用 标志位使线程停止,设置一个方法
调用testStop.stop();实现插队
线程休眠
调用Thread.sleep();实现休眠
线程礼让
礼让线程,让当前正在执行的线程停止,但不阻塞
将线程从运行状态转为就绪状态
让CPU调度,礼让不一定成功。看CPU的心情
在线程方法中加入Thread.yield();
线程强制执行
Thread.join();
观测线程状态
Thread.getState();
线程的优先级
线程.getPriority() 获取优先级 线程.setPriority();设置优先级
守护线程
线程分为用户线程和守护线程
虚拟机必须保证用户线程执行完毕
虚拟机不必等待守护线程执行完毕
案例:后台记录操作日志,监控 内存
thread.setDaemon(true)//默认是false表示用户线程,正常线程都是用户线程
用户线程停止,守护线程还会执行一段时间
线程同步机制
多个线程操作同一资源
并发:同一个对象被多个线程同时操作
锁机制
每个对象都有一把锁sleep不会 释放锁
在对应方法处添加synchronized
缺陷:若将一个大的方法声明为synchronized将会影响效率
将变化的量写进synchronized()代码块
同步块:synchronized(obj){}
obj称为同步监视器
obj可以是任何对象,但推荐使用共享资源作为同步监视器
同步方法中无需指定同步监视器,
copyonwritearraylist
这是一个安全的对象
死锁产生的条件
- 互斥条件 一个资源每次只能被一个进程使用
- 请求与保持条件 一个进程因请求资源而阻塞,对以获得的资源保持不放
- 进程已经获得的资源 ,在未使用完之前,不能强行剥夺
Lock锁
java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具
锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源前应先获得Lock对象
RenntrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显示加锁,释放锁。
class A{
private final ReentrantLock lock = new ReenTrantLock();
public void m(){
lock.lock();
try{
1/保证线程安全的代码;
}
finally{
lock.unlock);
1/如果同步代码有异常,要将unlock()写入finally语句块
}
}
}
synchronized与Lock的对比
- Lock是显示锁(手动开启和关闭,别忘了关闭锁)synchronized是隐式锁,出了作用域就自动释放
- Lock只有代码块锁,synchronized有代码块锁和方法锁
- 使用Lock锁,jvm将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性
- 优先使用顺序
Lock》同步代码块》同步方法