类加载的完整过程:
加载 --> 链接(验证 -> 准备 -> 解析)–> 初始化
加载阶段:
1.通过类的全限定类名将这个类的二进制字节流加载到方法区(类变量)。
链接阶段:
1.(验证)校验虚拟机字节流中包含信息是否符合当前虚拟机的要求。
2.(准备)为类变量设置默认初始值,final修饰的在编译时候就会分配内存,在准备阶段进行显式初始化,而实例变量被分配到java堆中。
3.(解析)将常量池内的符号引用转换为直接引用的过程;解析是在jvm执行初始化之后再执行。
初始化阶段:
1.进行类构造器方法的过程,jvm执行子类构造器,要先确保父类构造器已经执行完毕,jvm保障一个类的构造器在多线程的情况下被同步加锁;执行完毕后类的加载就完成了。
Eureka(类似zookeeper):
服务启动的时候,服务上的Eureka客户端会把自身注册到Eureka服务端,并且可以通过Eureka服务端知道其他注册的服务
Ribbon(负载均衡,默认轮询):
服务间发起请求的时候,服务消费者方基于Ribbon服务做到负载均衡,从服务提供者存储的多台机器中选择一台,如果一个服务只在一台机器上面,那就用不到Ribbon选择机器了,如果有多台机器,那就需要使用Ribbon选择之后再去使用
Feign(类似于dubbo;典型的rpc框架,不需要了解底层网络协议,就可以是实现远程调用):
Feign使用的时候会集成Ribbon,Ribbon去Eureka服务端中找到服务提供者的所在的服务器信息,然后根据随机策略选择一个,拼接Url地址后发起请求
Hystrix(熔断器进行服务降级):
发起的请求是通过Hystrix的线程池去访问服务,不同的服务通过不同的线程池,实现了不同的服务调度隔离,如果服务出现故障,通过服务熔断,避免服务雪崩的问题 ,并且通过服务降级,保证可以手动实现服务正常功能
Zuul(类似于nginx):
如果前端调用后台系统,统一走zull网关进入,通过zuul网关转发请求给对应的服务
一、悲观锁
顾名思义,就是对于数据的处理持悲观态度,总认为会发生并发冲突,获取和修改数据时,别人会修改数据。所以在整个数据处理过程中,需要将数据锁定。
悲观锁的实现,通常依靠数据库提供的锁机制实现,比如mysql的排他锁,select … for update来实现悲观锁。
将商品库存数量nums字段类型设为unsigned,保证在数据库层面不会发生负数的情况。
注意,使用悲观锁,需要关闭mysql的自动提交功能,将 set autocommit = 0;
注意,mysql中的行级锁是基于索引的,如果sql没有走索引,那将使用表级锁把整张表锁住。
乐观锁是基于程序实现的,所以不存在死锁的情况,适用于读多的应用场景。如果经常发生冲突,上层应用不断的让用户进行重新操作,这反而降低了性能,这种情况下悲观锁就比较适用。
迭代器的使用方法: