1.线程状态
Java 6种
新建
可运行 阻塞,有时等待,无限等待
终结
操作系统 5种
新建
就绪 阻塞
运行
终结
2.线程池七大参数
1.corePoolSize
2.maxinumPoolSize
3.keepAliveTime 急救线程生存时间
4.unit 急救线程的生存时间单位
5.workQueue 当线程分配完后,新任务来此排队
6.threadFactory 线程工厂,可以对线程进行一些个性化设置
7.handler 拒绝策略,当线程满了,队列满了,会触发拒绝策略
1.抛异常
2.丢弃任务
3.丢弃最早排队任务
4.由调用者执行任务
3.wait 和 sleep
相同(1):作用都是让当前线程放弃cpu的执行权,进入阻塞状态
不同(3):
归属不同:wait是Object的方法,sleep是线程的静态方法
醒来不同:sleep是暂时休眠后自动醒来,wait需要其他线程notify
锁特性不同:sleep休眠时放弃cpu,但是其他线程任不可使用。
wait放弃cpu,其他线程可以使用。待其他线程结束后,会更具程序计数器恢复它的后续程序。
4.Lock 和 synchronized
不同点(3)
语法:synchronized 是关键字,源码在jvm种,用c++实现
Lock 是接口,源码由jdk实现,用Java实现
synchronized 可以自动释放锁,Lock 需要调用 unlock 方法释放
功能:
都是悲观锁,均有互斥,同步,锁重入
Lock 提供了许多 synchronized 不具备的功能,如等待状态,公平锁,可打断,可超时,多条件变量
Lock 由适合不同场景的实现,如 reentrant,reentrantReadWriteLock
性能:
在没有竞争时,synchronized 有不错的性能
竞争激烈时,Lock通常会有更好的性能
公平锁:
已经处在阻塞队列的线程,始终是先进先出
公平锁是指未处于阻塞队列中的线程来争夺锁,如果队列不为空,则老实到队尾排队
非公平锁是指未处于阻塞队列的线程来争夺锁,与唤醒的对头去争抢,抢到谁的就是谁的
条件变量:
ReentrantLock 中的条件变量,功能类似于 synchronized 的 wait,notify,用在当线程获得锁后,发现条件不满足,临时等 待的链表结构。
与 synchronized 的等待集合不同之处在于,ReentrantLock 的条件变量可以有多个,可以实现更精确的等待、唤醒机制
5.volatile
原子性
起因:多线程条件下,不同线程的指令发生交错导致共享变量的读写混乱
解决:使用悲观锁,乐观锁实现
有序性(√)
起因:由于编译器优化、或缓存优化、或cpu指令重排序优化导致的对共享变量所做的修改其他线程看不到
解决:使用 volatile 修饰共享变量
可见性(√)
起因:由于编译器优化、或缓存优化、或cpu指令重排序优化导致指令的实际执行顺序和编写顺序不一样
解决:用 volatile 修饰共享变量会在读、写共享变量时加入不同的屏障,阻止其他读写越过屏障,从而达到阻止指令重排序
先写在读,因为写会在该变量上方加一个屏障,防止下面的指令放到上面
因为读会在该变量下方加一个屏障,防止上面的指令放到下面
6.悲观锁和乐观锁
悲观锁的代表:synchronized 和 Lock
乐观锁的代表:atomicInteger,使用 CAS 来保证原子性
其核心思想是【不加锁,每次仅有一个线程可以成功修改变量,其他失败的线程不需要停止,不断重试,直到成功】
由于线程一致运行,没有阻塞,没有上下文切换
需要多核cpu支持,且线程数不应该超过cpu核数
7.线程有几种创建方式
oracle 官方是两种,实现 runnable 和 继承 thread,具体使用还有其他三种,线程池,callable,timer
8.HashTable vs ConcurrentHashMap
都是线程安全的集合
Hashtable 并发度低,整个 HashTable 对应一把锁,只能有一个线程操作它
ConcurrentHashMap 并发度高,整个 ConcurrentHashMap 对应多把锁,只要线程访问的是不同锁,就不会发生冲突
9. ThreadLocal
ThreadLocal 可以实现【资源对象】的线程隔离,让每个线程各用各的【资源对象】,避免争用引发的线程安全问题
ThreadLocal 同时实现了线程内的资源共享
作者:万能包哥 出处:http://www.cnblogs.com/mybloger/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 如果文中有什么错误,欢迎指出。以免更多的人被误导。 |