记录从《java 多线程变成核心技术》学到的知识
对象及变量的并发访问
名词及方法解释
非线程安全
非线程安全主要是指多个线程对同一个对象中的同一个实例变量进行操作时会出现值被更改、值不同步的情况,从而影响程序的执行流程。(如果是方法内部的私有变量,则不存在线程安全问题)
死锁
- 互相等待对方释放锁就有可能出现死锁
- 某一线程执行同步代码时,暂停,无线循环。会导致这段代码被死锁
synchronized
- 父子类继承关系时,子类完全可以通过“可重入锁”调用父类的同步方法
- 当一个线程执行的代码出现异常时,其所持有的锁会自动释放
- 同步方法不能继承,子类中仍要手动添加synchronized关键字
- 只要对象不变,即使对象的属性被改变,该对象锁对应的方法/代码块仍然是同步的
- synchronized可以是多个线程访问同一资源具有同步性,而且它还具有将线程工作内存中的私有变量与公共内存中的变量同步的功能。
修饰方法和代码块:
修饰普通方法
synchronized在方法上加锁,默认锁为当前对象。可以阻塞synchronized标识的方法、synchronized(this)标识的代码块。修饰普通代码块
synchronized(anyObject) 在代码块上加锁,默认锁为anyObject对象。可以阻塞anyObject对象中synchronized标识的方法、synchronized(this)标识的代码块、其他对象中synchronized(anyObject)标识的代码块。
synchronized(anyObject) 在代码块上加锁,默认锁为anyObject对象。可以阻塞anyObject对象中synchronized标识的方法、synchronized(this)标识的代码块、其他对象中synchronized(anyObject)标识的代码块。- 修饰静态方法/静态代码块
持有的锁为Class对应的锁。和对象锁互不阻塞。
volatile
volatile关键字的作用是强制从公共堆栈中取的变量的值,而不是从私有数据栈中取得变量的值(当JVM被设置为-server模式执行时,为了提高线程运行效率,设置线程从私有数据栈中取值)
- volatile只能修饰变量
- 多线程volatile不会发生阻塞,synchronized会出现阻塞
- volatile保证数据可见性,不能保证院子性,synchronized可以保证原子性,间接的保证了可见性。
- volatile解决可见性,synchronized解决访问资源的同步性
currentThread()
currentThread()方法可返回代码段正在被哪个线程调用
isActive()
isActive方法是判断当前的线程是否处于活动状态
static sleep()
sleep()方法在指定的毫秒内让当前“正在执行的线程”休眠(暂停运行)
getId()
getId()获取线程的唯一标识。
stop()
停止一个正在运行的线程
interrupt()
中断线程,但这个方法不会终止一个正在运行的线程,还需要加入一个判断才可以完成线程的停止。
static interrupted()
测试当前线程(当前线程是指运行this.interrupted()方法的线程)是否已经是中断状态,执行后具有将状态标志清除为false的功能
isInterrupted()
测试线程Thread对象(this这个线程)是否已经是中断状态,但不清除状态标志
suspent()
暂停线程。慎用线程暂停,导致方法死锁
resume()
恢复线程的执行
yield()
yield()方法的主要作用是放弃当前cpu资源,将它给其他任务去占用cpu执行时间
setPriority
设置线程优先级
知识点
线程的优先级
- MIN_PRIORITY = 1;
- NORM_PRIORITY = 5;
- MAX_PRIORITY = 10;
终止线程的方法
- 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止
- 使用stop方法强行终止线程(不推荐),stop和suspend及resume一样都是作废过期的方法,使用它们可能产生不可预料的结果(什么不可预料的结果?)
- 使用interrupt方法中断线程
实现手动线程停止
使用this.interrupted()配合 thread.interrupt()使线程停止
使用stop暴力停止
使用使线程睡眠(run()方法中加Thread.sleep())配合thread.interrupt()使线程停止,需要捕捉InterruptedException异常