双亲委派机制: 先调用父类加载器,父类加载失败后才自己尝试加载
作用:保证核心类不被更改,避免重复加载
JAVA_HOME/jre/lib/ext/
目录下的所有jar包或者由java.ext.dirs系统属性指定的jar包BIO:同步阻塞(blocking-IO)
NIO:同步非阻塞(non-blocking-IO)
AIO:异步非阻塞(synchronous-non-blocking-IO)
举个通俗的例子:你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。
线程池大小设置:
public ThreadPoolExecutor(int corePoolSize, // 线程池的核心线程数
int maximumPoolSize, // 线程池的最大线程数
long keepAliveTime, // 当线程数大于核心时,多余的空闲线程等待新任务的存活时间。
TimeUnit unit, // keepAliveTime的时间单位
ThreadFactory threadFactory, // 线程工厂
BlockingQueue<Runnable> workQueue,// 用来储存等待执行任务的队列
RejectedExecutionHandler handler // 拒绝策略
)
1、懒汉式,线程不安全
public class Singleton {
private static Singleton instance;
private Singleton (){
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2、懒汉式,线程安全
public class Singleton {
private static Singleton instance;
private Singleton (){
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3、饿汉式
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){
}
public static Singleton getInstance() {
return instance;
}
}
4、双重校验锁(DCL,即 double-checked locking)
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
5、静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){
}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
6、枚举
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
1、ConcurrentHashMap:
2、Runnable
3、ReentrantLock
4、CyclicBarrier 循环栅栏:用于多个线程互相等待,每次调用await() 方法,计数器减一
5、CountDownLatch:用于一个线程等待多个线程,每次调用countdown() 方法,计数器减一
6、Semaphore 信号量:semaphore.acquire();
和 semaphore.release();
7、Exchanger:可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据。
8、ArrayBlockingQueue 和 LinkedBlockingQueue:
ArrayBlockingQueue | LinkedBlockingQueue | |
---|---|---|
阻塞实现方式 | 通知模式实现 | 通知模式实现 |
大小 | 必须指定初始化大小 | 构造器可以不初始化,默认为INTEGER.MAX_VALUE |
插入取出元素是否会创建和销毁元素 | 不会 | 会 |
生产者消费者锁的使用情况 | 同一把锁 | 各自使用不同的锁 |
1、所谓公平锁,就是线程按照执行顺序排成一排,依次获取锁
2、非公平锁和公平锁的两处不同
1、synchronized和volatile,特性上最大的区别就在于原子性,volatile不具备原子性
2、偏向锁、轻量级锁,重量级锁;只能升级,不能降级
3、锁的升级过程
为什么要引入轻量级锁?:
阻塞线程需要CPU从用户态转到内核态,代价较大,自旋等待一会儿
线程1获取轻量级锁时会先把锁对象的对象头MarkWord复制一份到线程1的栈帧中创建的用于存储锁记录的空间,然后使用CAS把对象头中的内容替换为线程1存储的锁记录的地址;
如果在线程1复制对象头的同时(线程1在CAS之前),线程2也准备获取锁,复制了对象头到线程2的锁记录空间中,但是线程2在CAS的时候,发现线程1已经把对象头换了,线程2的CAS失败,那么线程2就尝试使用自旋锁来等待线程1释放锁。
轻量级锁的升级的两种情况
1、但是如果自旋的时间太长也不行,因为自旋是要消耗CPU的,因此自旋的次数是有限制的,如果自旋次数到了线程1还没有释放锁;
2、或者线程1还在执行,线程2还在自旋等待,这时又有一个线程3过来竞争这个锁对象
3、那么这个时候轻量级锁就会膨胀为重量级锁。重量级锁把除了拥有锁的线程都阻塞,防止CPU空转。
hashCode & oldCap
判断是否为零,然后插入两个list,最后把两个list放在新的桶中。ConcurrentHashMap
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
// 可以看到这些都用了volatile修饰
volatile V val;
volatile Node<K,V> next;
}
1、GC Root:
2、方法: 标记清除,标记整理,复制
3、垃圾回收的空间
4、垃圾收集算法
lsof -i:8080
lsof -i
netstat
本文是想到某个知识点就查,相当于一个汇总,前期很多参考没写出来
Java并发——Synchronized关键字和锁升级,详细分析偏向锁和轻量级锁的升级