java基础知识--02
树越要往上长,它的根,越是要往下扎。
共勉!
synchronized
1、synchronized修饰代码块
2、synchronized修饰类的普通方法
3、synchronized修饰类的静态方法
重量级锁锁对象的原理(初学者的理解,可能有误):

修饰理解:
1、synchronized修饰代码块
同步语句块的实现使用的是monitorenter 和 monitorexit 指令。
2、synchronized修饰类的普通方法
锁的是这个对象。如对象多个普通方法被修饰,同一个对象访问这些方法时,公用一个锁。访问其他没有被synchronized修饰的普通方法,不受锁约束。
不同对象的锁不同,互不影响
3、synchronized修饰类的静态方法
锁是类锁(.class)。这个范围就比对象锁大。这里就算是不同对象,但是只要是该类的对象,就使用的是同一把锁。多个线程调用该类的同步的静态方法时,都会阻塞。
四种锁:
偏向锁
如果一个线程获得了锁,那么锁就进入偏向模式。
轻量级锁
倘若偏向锁失败,虚拟机并不会立即升级为重量级锁,它还会尝试使用一种称为轻量级锁的优化手段(1.6之后加入的)。线程运行到安全点后,对象的Mark Word 的结构转为轻量级锁,原持有线程的的锁信息也跟着升级为轻量级锁,与原线程竞争的外来线程进入自旋。
自旋锁
轻量级锁失败后,虚拟机为了避免线程真实地在操作系统层面挂起,还会进行一项称为自旋锁的优化手段。
重量级锁
如果锁竞争情况严重,某个达到最大自旋次数的线程,会将轻量级锁升级为重量级锁(依然是CAS修改锁标志位,但不修改持有锁的线程ID)。
锁消除
编译时去除不可能存在共享资源竞争的锁,如StringbBuffer自动转为StringBuilder
参考连接0:
https://blog.csdn.net/qq_40949465/article/details/88734834
参考连接1:
https://www.cnblogs.com/xiaolovewei/p/9152718.html
自旋锁:
https://www.jianshu.com/p/9d3660ad4358?utm_source=oschina-app
HTTP和HTTPS
https是在http基础上加上安全传输协议,加上SSL/TLS,http常用端口80,https是443
SSL(Secure Sockets Layer、安全套接层协议)
TLS(Transport Layer Security、安全传输层协议),是SSL 3.0的后续版本
原理流程:
1、服务器端存在公钥和私钥,浏览器请求服务器,服务器返回公钥
2、浏览器生成随机密钥 A
3、用服务器给的公钥,加密(非对称)A,传给服务器
4、服务器用私钥解密(非对称)A
5、至此,浏览器、服务器都有明文的 A,后续通讯信息,都用A来对称加密
参考连接:
https://blog.csdn.net/liuxingrong666/article/details/83869161
单例模式
一个类只允许有一个实例
构造函数私有化,对外暴露一个获取对象的接口,在类中创建唯一的一个静态实例对象。
破坏单例模式:
序列化后反系列化
反射
clone
防止破坏单例模式:
1、防止反射
定义一个全局变量,当第二次调用构造方法时抛出异常
2、防止克隆破坏
重写clone(),直接返回单例对象
3、防止序列化破坏
添加readResolve(),返回Object对象。
当JVM从内存中反序列化地"组装"一个新对象时,就会自动调用这个 readResolve方法来返回我们指定好的对象了, 单例规则也就得到了保证
参考连接0:
https://blog.csdn.net/fd2025/article/details/79711198
参考连接1:
https://blog.csdn.net/fd2025/article/details/79711198
泛型
概念:泛型是一个未知的数据类型
E e:Element 元素,E通常用来表示集合类型中的元素类型
T t: 是一个泛型,传递什么类型,就返回什么类型
1、 定义在类上:public class className < T > { }
在类上定义的泛型,在类的普通方法中也可以使用,但是类方法中的静态方法不能使用,这也很好理解,静态方法不需要实例化也能直接使用,然而还未实例化之前,谁也不知道是什么类型,故不能在静态方法中使用。
2、定义在方法上:public static final < T > void methodName(T t){ }
留个疑问,为什么类中的泛型声明是在类名字后面,而方法的泛型声明是在返回类型前面?都放在名字后面不好吗。。。
泛型是先定义,后使用的。放在返回类型,是为了适应这种情况:
public static final < T > T methodName(T t){ }
3、泛型类派生子类
子类明确要使用什么类型的情况下,继承泛型类:
public class ChildClass extends ParentClass< String > { }
子类不明确要使用什么类型的情况下,继承泛型类:
public class ChildClass< T > extends ParentClass< T > { }
其实也没什么区别,你也可以这么写:
public class ChildClass< Integer> extends ParentClass< Integer> { }
通配符 ? :
不常用通配符,对通配符感悟不深。感觉使用了通配符反而不灵活了。
如果要使用通配符,则是配合PECS原则来限制集合的读取写入。
PECS原则(Producer Extends Consumer Super):
PE:
如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)
/**
* Created by HXH on 2021/3/18
* @desc
*/
public class TestPECS {
public static void main(String[] args) {
List<String> list = new ArrayList<>();//String集合
List<? extends Object> list1 = list;
for (Object s : list1){
//可以读取,因为不管是什么子集,都有Object类型帮它兜底,总是可以转化成功
}
//不能加入,虽然Integer是Object子类
//list1只知道类型上限是Object,却不知具体是什么类型,不能由父类转子类
//通俗一点的理解:可以看到list最先是List<String>类型,这里是Integer类型
list1.add(new Integer(1));//报错
list1.remove(0);//可以删除
}
}
CS:
如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)
//能操作下限类
List<Object> objectList = new ArrayList<>();
List<? super String> list = objectList;
list.add("555");//可以
list.add(new Object());//不行
//能操作下限类的子类
List<Number> numberList = new ArrayList<>();
List<? super Number> list2 = numberList;
list2.add(2f);//可以
list2.remove(3L);//可以
//读取
for (Number n : list2){
//不行
}
for (Object n : list2){
//只能用Object接收
}
参考连接0:
https://segmentfault.com/a/1190000014120746
参考连接1:
https://blog.51cto.com/flyingcat2013/1616068
浙公网安备 33010602011771号