Java多线程编程核心技术
第1章 Java多线程技能
使用多线程
继承Thread类
局限:不支持多继承
|
|
Thread.java类中的start()方法通知线程规划器此线程已经准备就绪,等待调用线程对象的run()方法,让系统安排时间调用Thread中的run()方法,使线程得到运行。启动线程,具有异步执行的效果。
如果调用代码thread.run()就不是异步执行,而是同步,由main主线程来调用run()方法,必须等run()方法中的代码执行完毕后才可以执行后面的代码。
实现Runnable接口
|
|
守护线程
当进程中不存在非守护线程,则守护线程自动销毁。典型的守护进程就是垃圾回收进程。
第2章 对象及变量的并发访问
synchronized同步方法
方法内的变量为线程安全
方法前加关键字synchronized
多个对象多个锁
关键字synchronized取得的锁都是对象锁,哪个线程先执行带synchronized关键字的方法,哪个线程就持有该方法所属对象的锁Lock,其他线程只能呈现等待状态,前提是多个线程访问的是同一个对象。
锁重入
一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远可以得到锁的。
出现异常,锁自动释放
当一个县城执行的代码出现异常时,其所持有的锁会自动释放。
同步不具有继承性
还要在子类的方法中添加synchronized关键字
synchronized同步语句块
当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized(this)同步代码块。
当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对于同一个object中所有其他synchronized(this)同步代码块的访问将堵塞。
synchronized关键字加到static静态方法上是给Class类上锁,而synchronized关键字加到非static静态方法上是给对象上锁
volatile关键字
通过使用volatile关键字,强制地从公共内存中读取变量的值。
使用volatile关键字增加了实例变量在多个线程之间的可见性,但最致命的缺点是不支持原子性
synchronized VS volatile
关键字
volatile是线程同步的轻量级实现,性能更好;volatile只能修饰与变量,synchronized可以修饰方法以及代码块。随着JDK新版本发布,
synchronized关键字在执行效率上得到很大提升多线程访问
volatile不会发生堵塞,synchronized会发生堵塞volatile能保证数据的可见性,但不能保持原子性;synchronized可以保证原子性,间接保证可见性关键字
volatile解决的变量在多个线程之间的可见性;关键字
synchronized解决的是多个线程之间访问资源的同步性;
非原子性
如果修改实例变量中的数据,比如i++,并不是一个原子操作,也就是非线程安全的
- 从内存中取出i的值
- 计算i的值
- 将i的值写到内存中
使用原子类进行i++操作
AtomicInteger原子类进行实现
第3章 线程间通信
通知等待机制
关键字synchronized可以将任何一个Object对象作为同步对象来看待,而Java为每个Object都实现了wait()和notify()方法,它们必须用在被synchronized同步的Object的临界区内。通过调用wait()方法可以使处于临界区内的线程进入等待状态,同时释放被同步对象的锁。而notify()操作可以唤醒一个因调用了wait()操作而处于堵塞状态中的线程,使其进入就绪状态。
调用方法notify()一次只随机通知一个线程进行唤醒;
为了唤醒全部线程,可以使用notifyAll()方法。
类ThreadLocal的使用
类ThreadLocal主要解决的就是每个线程绑定自己的值。
第4章 Lock的使用
使用ReentrantLock类
类ReentrantLock需要借助于Condition对象可以实现等待通知模式。
公平锁与非公平锁
公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序;
非公平锁就是一种获取锁的抢占机制,是随机获得锁的。
使用ReentrantReadWriteLock类
类ReentrantLock具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务,虽然保证了实例变量的线程安全性,但效率却是非常底下的。
读写锁表示也有两个锁,一个是读操作相关的锁,也成为共享锁;另一个是写操作相关的锁,也叫排他锁。多个读锁之间不互斥,写锁与读锁互斥,写锁与写锁互斥。多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。
第6章 单例模式与多线程
立刻加载
|
|
延迟加载
|
|
不能保证多线程安全
延迟加载的解决方案
synchronized关键字
|
|
效率低
双检查锁
|
|
第7章 其他
线程的状态
六种状态
- NEW
- RUNNABLE
- BLOCKED
- WAITING
- TIMED_WAITING
- TERMINATED
补充:五种状态
- 新建
- 就绪(RUNNABLE )
- 运行(RUNNABLE )
- 堵塞(BLOCKED, WAITING,TIMED_WAITING)
- 死亡