WORK-09- 学习笔记
JAVA 虚拟机
JAVA 是跨平台的语言;
JVM 屏蔽了底层系统的不同,为 JAVA 字节码文件构造了一个统一的运行环境。
类文件->类加载器
方法区 JAVA 栈
堆 程序计数寄存器
执行引擎
方法区和堆是所有线程共享的数据区;
JAVA 栈和程序计数寄存器是每个线程独享的运行期数据区
程序计数寄存器是给程序调用,记录字节码到哪一行。
NEW 的 CLASS 是在堆内的 ;
执行引擎是 LINUX 下的 X86
JAVA 编译出来的可以在执行引擎上执行;
因为不同的环境上的执行引擎不一样,将 JAVA 字节码转换成本地操作系统认识的代码执行。
Java 启动一定要跟一个类,一定要有 MAIN 方法。
JAVA 启动虚拟机,初始化环境,内存空间等;装载这个类,放到方法区,由主线程,从 MAIN 方法开始执行,当前的线程会在 JAVA 栈创建一个栈帧放在 JAVA 栈的顶部。
NEW 的过程是执行引擎来做的,所有的代码都是执行引擎来做;
装载类都是类加载器来做的,装载到方法区内做。
JAVA 字节码文件;
计算机领域的任何问题都可以通过增加一个中间层(虚拟层)来解决。
(上次是一致性 HASH 内解决)
JAVA 所有的指令由 200 个,一个字节(8 位)可以存储 256 种不同的指令信息,一个这样的字节称为字节码。
字节码的执行过程:
JAVA 字节码文件编译过程;
类加载器的双亲委托模型
加载过的类不会加载
BOOTSTRAP CLASSLOADER
PLATFORM CLASSLOADER
APPLICATION CLASSLOADER
自定义类加载器:
可以自己写类加载器,继承 CLASSLOADER
每个 JVM 都有个唯一的堆;【都在内存中】
栈 :程序的栈帧
堆: 对象存堆
方法区(特殊区域):静态变量 静态方法存这里;
JAVA 线程栈
基本类型的变量,都被每个运行这个方法的线程放入自己的栈中;
线程工作内存 & volatile
多线程的情况下,共享变量(类的成员变量、类的静态成员变量)被 volatile 修饰后,保证不同线程堆这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值堆其他的线程来说是立即可见的。
JAVA 垃圾回收
JVM 来及回收就是将 JVM 堆中已经不再使用的对象清理掉;释放宝贵的内存资源;
JVM 通过一种可达性分析算法进行垃圾对象的识别;
从线程栈以及静态区中,逐层找被引用的对象,未被标记的就回收或压缩;
JVM 分代垃圾回收
新生代,
老年代,
创建一个对象再 EDEN 区,当 EDEN 区满了后,启动一次新生代的垃圾回收,把有引用的 COPY 到 FROM 区内
通常新生代得设置比老年代小很多。
JVM 垃圾回收算法,
JSTAT 是 JDK 自带得一个轻量级得小工具,主要对 JAVA
jstat -gcutil 94685 1000 10
应用时间不稳定
JMAP
JSTACK 可以查看 JVM 内的线程堆栈信息;
JVISUALVM
JAVA 代码优化
合理并谨慎使用多线程;
线程上下文切换也是消耗 CPU 资源的事情;
理论上:
启动的线程数= 【任务执行时间/(任务执行时间-IO 等待时间)】 * CPU 内核数
如果没有阻塞,那么线程数就是内核数
如果有网络阻塞,磁盘等待,那么可以多启动线程;
竞态条件与临界区
在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问
JAVA 线程安全;
允许被多个线程安全执行的代码被称为线程安全的代码;
方法局部变量:局部变量不会被多个线程共享,所以基础类型的局部变量都是线程安全的;
方法局部的对象引用:
某个方法中创建的对象不会逃逸出该方法,那么它就是线程安全的;
对象成员变量:
对象成员存储在堆上,如果两个线程同时更新同一个对象的同一个成员,那么这个代码就不安全了。
JAVA WEB 应用的多线程是从哪里来的?
回答: 是容器中来的;
SERVLET 是线程安全的吗?(CTO 面试题)
回答:
SERVLET 是单实例
THreadLocal
线程共享 线程私有
threadlocal 是放在堆内的;
但是每个线程都能设置自己的值,并能获取自己设置的值,
实现原理:THreadLocal 内部设置了个 map KEY 就是 线程
内存泄漏
spring MVC 的 contorller
JVM 回收原理 面试题
秒杀系统
XXX 网站的正常流程情况:
并发单台,高峰期<10;
吞吐量(TPS,单台)高峰期,<60
CPU 负载 LOAD 高峰期,<2,发部分服务器<1
CPU 使用率,一般只占 1 颗核,平均 60%左右
服务器平均响应事件 高峰期 ,<150 ms;
图片总流量带宽 1.8G (各网站总合)
高并发下的风险
网络带宽耗尽
服务器 LOAD 飙高,停止响应
数据库瘫痪
高并发下的事故
图片过大,导致带宽耗尽,
运营推广的图片流量不能超过现有流程的 30%;
秒杀
高并发对网站性能的影响:
并发数对吞吐量的影响;
并发数对用户响应事件的影响;
高并发实例:XXX.COM 开业秒杀活动
商业需求:
技术挑战:
系统只能提升 50% 100%这样的性能;
逐步迭代,花个半年~几年,来增加几倍,几十倍;
不可能 5 天把一个几百个人维护的系统
之前提的那么多优化方案,不可能短期内搞定;
解决方案:重新在前面做个秒杀系统;
开发个新系统远远比维护一个老系统的要
什么样回报更高,做一个新的系统;
做新的系统,没有历史包袱;
8000 并发
style 服务器:LIGHTTPPD 集群:5 台;
图片服务器:NGINX 集群,5 台
静态服务器:APACHE 集群,10 台
交易服务器:JBOSS 动态集群,10 台
秒杀系统:组成
商品列表和介绍:【XXX.COM】静态集群
填写订单页面
对于秒杀来说,
商品列表和商品介绍就写成静态的页面,这样就不用对数据库操作了。
静态化:
--采用 JS 自动更新技术将动态页面转化为静态页面;
关键点 1:页面可配置,通过设置定时器,将静态页面提前生成推送到静态资源服务器;
关键点 2:秒杀商品列表/秒杀商品介绍页面,如何判断秒杀开始否?
商品 ID 从后台获取,
并发控制,防秒杀器:
设置阀门
三道阀门的设计
分布式缓冲,三个计数器;
计数器 1:限制进入秒杀界面,1000; ---所有的压力在这个界面就处理掉了,到下个界面压力就降了;
计数器 2:限制进入下单页面,100;
计数器 3:限制进入支付系统,56;
所有数据库操作全部砍掉;
应急预案:独立域名,不影响 XXX 原有业务
机动服务器:10 台
拆东墙补西墙:
壁虎断尾:
万能出错页面:
总结:
JVM 的回收机制要理解,才能更好的帮助我们完事优化程序,防止内存泄露,提高服务器性能。
秒杀系统的实现思路和方法其实并不是很多高大上的技术,但是都是能解决问题的实用的技术和思维方法,说明我们要把这些思维方法和技术深入理解,举一反三,变成潜意识的理解。
评论