JVM虚拟机原理

JVM组成架构

Java是一种跨平台的语言,JVM屏蔽了底层系统的不同,为Java字节码文件构造了一个统一的运行环境。

Java 字节码文件

Java 如何实现在不同操作系统、不同硬件平台上,都可以不用修改代码就能顺畅地执行?

计算机领域的任何问题都可以通过增加个中间层(虚拟层)来解决

Java所有的指令有200个左右,一个字节(8位)可以存储256种不同的指令信息,一个这样的字节称为字节码(Bytecode)。在代码的执行过中,JVM将字节码解释执行屏蔽对底层操作系统的依赖,JVM也可以将字节码编译执行,如果是热点代码,会通过JIT动态地编译为机器码,提高执行效率

字节码执行流程

Java字节码文件编译过程

类加载器的双亲委托模型

低层次的当前类加载器,不能覆盖更高层次类加载器已经加载的类。如果低层次的类加载器想加载一个未知类,需要上级类加载器确认,只有当上级类加载器没有加载过这个类,也允许加载的时候,才让当前类加载器加载这个未知类。

自定义类加载器

  • 隔离加载类:同一个JVM中不同组件加载同一个类的不同版本。
  • 扩展加载源:从网络、数据库等处加载字节码。
  • 字节码加密:加载自定义的加密字节码,在ClassLoader中解密。

堆&栈

  • 堆:每个JVM实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享。
  • 堆栈:JVM为每个新创建的线程都分配一个堆栈。也就是说,对于一个 Java程序来说,它的运行就是通过对堆栈的操作来完成的。

Java 中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的引用而已。

方法区&程序计数器

方法区主要存放从磁盘加载进来的类字节码,而在程序运行过程中创建的类实例则存放在堆里。程序运行的时候,实际上是以线程为单位运行的,当JVM进入启动类的main方法的时候,就会为应用程序创建一个主线程,main方法里的代码就会被这个主线程执行,每个线程有自己的Java栈,栈里存放着方法运行期的局部变量。而当前线程执行到哪一行字节码指令,这个信息则被存放在程序计数寄存器。

package com.bjsxt.test;public class Demo01 {    public static void main(String[] args)        A a = new A();        System.out.println(A.width);    }}class A {    public static int width=100;    static{        System.out.println("静态初始化类A");        width=300;    }    public A(){        System.out.println("创建A类的对象");    }}

Java(线程)栈

所有在方法内定义的基本类型变量,都会被每个运行这个方法的线程放入自己的栈中,线程的栈彼此隔离,所以这些变量一定是线程安全的。

线程工作内存 & volatile

Java内存模型规定在多线程情况下,线程操作主内存变量,需要通过线程独有的工作内存拷贝主内存变量副本来进行。

一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

  • 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
  • 禁止进行指令重排序。

Java运行环境

JVM的垃圾回收

JVM垃圾回收就是将JVM堆中的已经不再被使用的对象清理掉,释放宝贵的内存资源。

JVM通过一种可达性分析算法进行垃圾对象的识别,具体过程是:从线程栈帧中的局部变量,或者是方法区的静态变量出发,将这些变量引用的对象进行标记,然后看这些被标记的对象是否引用了其他对象,继续进行标记,所有被标记过的对象都是被使用的对象,而那些没有被标记的对象就是可回收的垃圾对象了。

进行完标记以后,JVM就会对垃圾对象占用的内存进行回收,回收主要有三种方法

  • 清理:将垃圾对象占据的内存清理掉,其实JVM并不会真的将这些垃圾内存进行清理,而是将这些垃圾对象占用的内存空间标记为空闲,记录在一个空闲列表里,当应用程序需要创建新对象的时候,就从空闲列表中找一段空闲内存分配给这个新对象。
  • 压缩:从堆空间的头部开始,将存活的对象拷贝放在一段连续的内存空间中,那么其余的空间就是连续的空闲空间。
  • 复制:将堆空间分成两部分,只在其中一部分创建对象,当这个部分空间用完的时候,将标记过的可用对象复制到另一个空间中。

JVM分代垃圾回收

JVM垃圾回收器算法

G1垃圾回收内存管理机制

-XX:MaxGCPauseMillis

Java启动参数

标准参数,所有的JVM实现都必须实现这些参数的功能,而且向后兼容

  • 运行模式-server,-client
  • 类加载路径-cp,-classpath
  • 运行调试--verbose
  • 系统变量--D

非标准参数,默认jvm实现这些参数,但不保证所有jvm实现都实现,且不保证向后兼容

·-Xms初始堆大小

·-Xmx最大堆大小

·-Xmn新生代大小

·-Xss线程堆栈大小

非Stable参数,此类参数各个jvm实现会有所不同,将来可能会随时取消

·-XX:-UseConcMarkSweepGC 启用CMS垃圾回收

JVM 性能诊断工具

基本工具:JPS,JSTAT,JMAF

集成工具:JConsole,JVisualVM

JPS

JPS 用来查看 host 上运行的所有 java 进程的 pid (jvmid),一般情况下使用这个工具的目的只是为了找出运行的jvm进程ID,即lvmid,然后可以进一步使用其它的工具来监控和分析JVM。

常用的几个参数:

  • -l 输出java应用程序的main class的完整包
  • -q 仅显示pid,不显示其它任何相关信息
  • -m 输出传递给main方法的参数
  • -v 输出传递给JVM的参数。在诊断JVM相关问题的时候,这个参数可以查看JVM相关参数的设置

JSTAT

JSTAT("Java Virtual Machine statistics monitoring tool")是JDK自带的一个轻量级小工具。主要对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。

语法结构如下:jstat [Options] vmid [interval] [count]

  • Options -- 选项,我们一般使用 - gcutil查看gc情况
  • vmid -- VM的进程号,即当前运行的java进程号
  • interval -- 间隔时间,单位为毫秒
  • count -- 打印次数,如果缺省则打印无数次

S0 -- Heap上的 Survivor space 0 区已使用空间的百分比

S1 -- Heap上的 Survivor space 1区已使用空间的百分比

E -- Heap上的 Eden space 区已使用空间的百分比

O -- Heap上的 Old space 区已使用空间的百分比

YGC -- 从应用程序启动到采样时发生 Young GC 的次数

YGCT -- 从应用程序启动到采样时 Young GC 所用的时间(单位秒)

FGC -- 从应用程序启动到采样时发生 Full GC 的次数

FGCT -- 从应用程序启动到采样时 Full GC 所用的时间(单位秒)

GCT -- 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)

JMAP

JMAP是一个可以输出所有内存中对象的工具,甚至可以将VM中的heap,以二进制输出成文本。

使用方法

  • jmap-histo pid>a.log可以将其保存到文本中去,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。
  • jmap-dump:format=b,file=f1 PID可以将该PID进程的内存heap输出出来到f1文件里。

JConsole

JVisualVM

Java代码优化

合理并谨慎使用多线程

使用场景(1/0阻塞,多CPU并发)

资源争用与同步问题

java.util.concurrent

启动线程数=[任务执行时间/(任务执行时间−IO等待时间)]∗CPU内核数

  • 最佳启动线程数和CPU内核数量成正比,和IO阻塞时间成反比。如果任务都是CPU计算型任务,那么线程数最多不超过CPU内核数,因为启动再多线程,CPU也来不及调度;相反如果是任务需要等待磁盘操作,网络响应,那么多启动线程有助于提高任务并发度,提高系统吞吐能力,改善系统性能。

竞态条件与临界区

在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源。

当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。导致竞态条件发生的代码区称作临界区。

在临界区中使用适当的同步就可以避免竞态条件。

Java线程安全

允许被多个线程安全执行的代码称作线程安全的代码。

局部变量

  • 局部变量存储在线程自己的栈中。也就是说,局部变量永远也不会被多个线程共享。所以,基础类型的局部变量是线程安全的。

局部的对象引用

  • 如果在某个方法中创建的对象不会逃逸出该方法,那么它就是线程安全的。

对象成员

  • 对象成员存储在堆上。如果两个线程同时更新同一个对象的同一个成员,那这个代码就不是线程安全的。

Java Web应用的多线程从哪儿来的?

  • 来自于容器

Servlet是线程安全的吗?

  • 不安全。Servlet是单实例的,所有的用户请求线程访问的是同一个Servlet,而Servlet里的成员变量就有可能被多线程同时修改、同时访问到。
  • 安全。一个Servlet安全不安全,Servlet本身是不知道的,你有多线程共享的变量你就是不安全的,没有共享变量的话就是安全的。Servlet本身是安全的,但是你写了一个不安全的类就会导致它不安全。

ThreadLocal

创建一个 Threadloca|变量

  • private ThreadLocal myThreadLocal = new ThreadLocal();

存储此对象的值

  • myThreadLocal.set("A thread local value");

读取一个 Threadlocal对象的值:

  • String threadLocalValue=(String) myThreadLocal.get();
public void set(T value){    Thread t = Thread.currentThread();    ThreadLocalMap map=getMap(t);    if (map != null)        map.set(this,value);    else        createMap(t,value);}void createMap (Thread t, T firstValue) {    t.threadlocals=new ThreadLocalMap(this,firstValue);}

Java内存泄漏

Java内存泄漏是由于开发人员的错误引起的。

如果程序保留对永远不再使用的对象的引用,这些对象将会占用并耗尽内存。

  • 长生命周期对象
  • 静态容器
  • 缓存

合理使用线程池和对象池

  • 复用线程或对象资源,避免在程序的生命期中创建和删除大量对象
  • 池管理算法(记录哪些对象是空闲的,哪些对象正在使用)
  • 对象内容清除(ThreadLocal的清空)

使用合适的JDK容器类(顺序表,链表,Hash)

  • LinkList和ArrayList的区别及适用场景
  • HashMap的算法实现及应用场景
  • 使用concurrent包,ConcurrentHashMap和HashMap的线程安全特性有什么不同?

缩短对象生命周期,加速垃圾回收

  • 减少对象驻留内存的时间
  • 在使用时创建对象,用完释放
  • 创建对象的步骤(静态代码段-静态变量-父类构造函数-子类构造函数)

使用I/O buffer及NIO

  • 延迟写与提前读策略
  • 异步无阻塞IO通信

优先使用组合代替继承

  • 减少对象藕合
  • 避免太深的继承层次带来的对象创建性能损失

合理使用单例模式

  • 无状态对象
  • 线程安全

虚拟化所有层次

  • 计算机的任何问题都可以通过间接层解决
  • 一致性hash算法的虚拟化实现
  • 面向接口编程
  • 7层网络协议

秒杀

XXXX 性能现状

XXXX网站的正常流量情况

  • 并发(单台),高峰期<10;
  • 吞吐量(TPS,单台)高峰期,<60;
  • CPU负载Load高峰期,<2,大部分服务器<1;
  • CPU使用率,一般只占1颗核,平均60%左右;
  • 服务器平均响应时间高峰期,<150ms;
  • 图片总流量带宽1.8G(各网站总合)。

高并发下的风险

  • 网络带宽耗尽
  • 服务器Load飘高,停止响应。
  • 数据库瘫疾

高并发下的事故

  • 事故:网站运营推广页面弹出1兆大图片导致带宽耗尽
  • 增加审核机制:运营推广增加的图片流量不能超过现有流量的30%
  • 合作媒体推广:迅雷,暴风影音浮出广告,导致ZZ集群Crash。

秒杀

  • XXXX.com开业88小时不间断秒杀活动

高并发对网站性能的影响

  • 并发数对吞吐量的影响

  • 并发数对用户平均请求等待时间的影响

  • 并发数对服务器平均请求响应时间的影响

高并发实例:XXXX.com开业秒杀活动

商业需求

  • 为庆祝XXXX.com开业推出88小时不间断秒杀活动。
  • 每小时整点推出8款商品......
  • 每款商品供168件,每人限批3件,成交人数56人。
  • CCTV黄金广告时间,各种网络,平面媒体轰炸,总广告费:1.5亿。
  • 接到运营通知,距秒杀开始仅仅5天时间。

技术挑战

  • 瞬间高并发
  • 8000并发:预估秒杀在线人数可达8000人。
  • 风险:带宽耗尽。
  • 服务器:崩溃,可以理解成自己给自己准备的D.D.O.S攻击。
  • 秒杀器
  • 第一种:秒杀前不断刷新秒杀页面,直到秒杀开始,抢着下单。
  • 第二种:跳过秒杀页面,直接进入下单页面,下单。

XXXX.com 秒杀系统:服务器和网络准备

服务器准备(距秒杀开始仅五天时间来不及采购)

  • style服务器(Lighttpd集群):5台
  • 图片服务器(Nginx集群):5台
  • 静态服务器(Apache集群):10台
  • 交易服务器(JBoss动态集群):10台

带宽准备

  • 图片出口带宽上限:2.5G(出口带宽支持10G,但图片服务器集群的处理能力:图片服务集群最大并发处理能力 * 网站平均图片大小=2.5G)
  • CDN准备:Chinacache沟通;借用CCCC CDN

XXXX.com 秒杀系统:架构目标

1.图片网络带宽:1.0G

新增图片带宽:必须控制在1.0G左右

每件商品秒杀页面的图片总大小不得超过:1000000/(1000*8)=125K/每商品

2.网站并发:

单件商品并发:1000【来自运营的预估】

总并发:8(件商品)*1000(人/商品)=8000

XXXX秒杀系统:组成

简单系统:

三个页面组成:秒杀商品列表,秒杀商品介绍,下单

XXXX.com 秒杀系统:设计原则

静态化

  • 采用JS自动更新技术将动态页面转化为静态页面

并发控制,防秒杀器

  • 设置阀门,只放最前面的一部分人进入秒杀系统

简化流程

  • 砍掉不重要的分支流程,如下单页面的所有数据库查询
  • 以下单成功作为秒杀成功标志。支付流程只要在1天内完成即可。

前端优化

  • 采用YSLOW原则提升页面响应速度

XXXX秒杀系统:静态化(1)

秒杀商品list和Detail是静态HTML页面

XXXX秒杀系统:静态化(2)

秒杀商品列表/秒杀商品介绍页面,如何判断秒杀开始否。

答案:valid-offer.js

var valid_offerIds=23624364,53778658,35885833,46999696,5006797057

三道阀门的设计

阀门:基于TT的计数器

秒杀器的预防

秒杀 Detail 页面

  • URL:随机
  • 秒杀前2秒放出,脚本生成,秒杀前。
  • 1000次访问上限控制【每件商品只能放入1000人浏览】。

下单页面:

  • 订单ID,随机。
  • 不能直接跳过秒杀Detail页面进入。
  • 每个秒杀商品,带预先生成的随机Token作URL参数。
  • 如果秒杀过,直接跳到秒杀结束页面。
  • 100次访问上限控制【每件商品只能放入100人下单】。

Web Server 调优-Apache调优

  • KeepAlive 相关参数调优

  • 其他参数调优
  • HostnameLookups设为off,对allowfromdomain等后的域名不进行正向和反向的dns解析。
  • 关闭cookies-log日志
  • 打开 Linux sendfile()
  • 关闭无用的module
  • mod_Gzip
  • (秒杀页面,非图片HTML文本所占流量比重可忽略不计,zip意义不大)
  • mod_Beacon
  • mod_hummock(等待反应过来,秒杀已经over了)

Web Server 调优-JBoss调优

Mod-jk worker 调优

JkWorkerProperty worker.list=localnodeJkWorkerProperty worker.localnode.port=7011JkworkerProperty worker.localnode.host=localhostJkWorkerProperty worker.localnode.type=ajp13JkWorkerProperty worker.localnode.ibfactor=1  JkWorkerProperty worker.localnode.socket_keepalive=TrueJkWorkerProperty worker.localnode.socket_timeout=20JkWorkerProperty worker.localnode.connection_pool_minsize=25JkWorkerProperty worker.localnode.connection_pool_timeout=600

JBoss AJP Connector

Tomcat APR 设定

秒杀静态页面优化

图片合并

  • 8张图片合并成1张,CSS偏移展示。
  • 减少HTTP请求数,减少请求等待数。
  • 减少发送Cookies的量。

HTML内容压缩

图片压缩:图片 Bytes < 长*宽/2250

HTML Header Cache-Control 设置

CSS, JS精简

  • CSS,JS精简到极致,部分直接写在页面中,减少HTTP请求次数。

下单页面优化

数据库操作:全部砍掉

  • 原下单页面要访问8次数据库,全部砍掉。

秒杀流程精简

  • 砍掉填写或选择收货地址,放在秒杀成功后填写。
  • 砍掉调用是否开通支付接口,秒杀首页文案提示必须开通。

采用内存缓存

  • 秒杀Offer数据,支付相关信息,缓存。

交易系统性能优化

  • 交易系统调优目标:

  • 关闭KeepAlive(分析交易系统 accesslog,用户在短时间内连续点击概率很低)
  • JVM优化
  • 优化CMS垃圾回收器的参数
  • 消灭Top10Bottlenecks
  • Velocity参数调优
  • 采用DBCP1.4替换C3P0
  • Offer产品参数的XML解析

二跳页面的优化

XXXX.com其他页面

  • 前端优化:Yslow规则调优
  • 减少HTTP请求,合并JS,CSS,图片,充分利用浏览器缓存。
  • 图片压缩,公式: 图片 Bytes < 长*宽/2250
  • 避免发送Cookies

交易系统优化

  • 普通订单管理列表和XXXX秒批订单管理列表分离
  • 禁止用模糊查询功能

应急预案

  • 域名分离,独立域名,不影响XXXX原有业务。

>Style集群:style.XXXX.china.XXXX.com

>图片服务器集群:img.XXXX.china.XXXX.com

>静态页面集群:page.XXXX.china.XXXX.com

>出问题直接把XXXX相关域名卡掉,所有请求跳到万能出错页面。

  • 机动服务器10台,备用。
  • 拆东培补西墙战略

>5天时间来不及采购服务器,因此SA待命,随时准备将非核心应用集群的兄余服务器下线,加入到秒杀集群。

  • 壁虎断尾策略

>所有办法均失效的情况下,例如流量耗尽。

>非核心应用集群统统停止服务,如资讯,论坛,博客等社区系统。

>保住首页,Offer Detail,旺铺页面等核心应用的可用性。

  • 万能出错页面:秒杀活动已经结束

>任何出错都302跳转到此页面

>位于另外集群

  • 万幸:最终所有的预案都没有用上

秒杀活动结果

88小时秒杀,坚守阵地,大获成功。

秒杀还是被秒杀?终于有了答案

三道阀门设计非常有效,拦住了秒杀器。

  • XXXX.com 静态集群总并发情况(首页,秒杀列表,秒杀商品页面)

  • 交易系统集群总并发情况(下单页面)

改进一:采用更轻量/快速的服务器(1)

采用 Lighttpd 替代 Apache 杀手铜(AIO)

Lighttpd 1.5 VS Apache2.2.4

小页面性能(100K)

  • http_load-verbose-timeout 40-parallel 100-fetches 500 http-load.10M.urls-100M

大页面性能(10M)

性能关键:Web Server的高性能I/O

XXXX应用服务器升级项目:

Apache2.2+Mod-Proxy+Jetty7.1.5 与XXXX现有架构性能对比:

性能大幅提升,XXXX全站下线1/3应用服务器(100台,明年不用采购新机器)

架构更轻量,配置更简单

应用更无状态化,开发和维护的福音

更加安全

改进二:前端优化自动化

  • XXXX服务器响应时间<150ms,但Offer Detail 页面用户等待时间5s,大部分时间耗在路上(资源请求和网络传输)
  • 图片自动压缩(CMS自动压缩)
  • Cookies服务化(控制Cookies的大小)
  • XXXX前端延迟加载框架SmartLoad(只加载首屏数据)
  • Google mod pagespeed module
  • 自动压缩图片,静态资源,智能浏览器缓存技术
  • Google Diffable(增量下载静态资源技术)

改进三:架设镜像站组建山寨CDN

XXXX 青岛镜像站项目

改进四:采用反向代理加速核心页面

在Offer集群前部署 Squid反向代理集群

  • Offer Detail的Squid反向代理改造

  • 基于消息的Squid缓存更新机制

改进五:海量数据的透明垂直切分

XXXX 性能优化领域立项中

搜索引擎

  • 互联网搜索引擎整体架构
  • 爬虫系统架构

  • 爬虫禁爬协议
  • User-agent: GoogleBot
  • Disallow: /tmp/
  • Disallow: /cgi-bin/
  • Disallow: /users/paranoid/
  • 文档矩阵与倒排索引
  • 文档与倒排索引
  • 带词频的倒排索引
  • 带词频与位置的倒排索引
  • Lucene架构

  • Lucene倒排索引

  • Lucene索引文件准实时更新
  • 索引有更新,需重新全量创建一个索引来替换原来的索引,这种方式在数据量大时效率很低,并且由于创建一次索引的成本很高,性能也很差
  • Lucene中引入了段的概念,将一个索引文件拆分为多个子文件,每个子文件叫做段,每个段都是一个独立的可被搜索的数据集,索引的修改针对段进行操作
  • 新增:新数据需要创建索引,选择新建一个段来存储新增的数据
  • 删除:当需要删除数据时,在索引文件新增一个.del的文件,用来专门存储被删除的数据ID
  • 更新:是删除与新增的组合
  • 为了控制索引里段的数量,必须定期进行段合并操作
  • ElasticSearch架构

(Lucene缺点是不支持分布式,数据量很大时考虑ElasticSearch)

  • 索引分片,实现分布式
  • 索引备份,实现高可用
  • API更简单、更高级
  • ES分片预分配与集群扩容

  • shard = hash(routing)%number_of_primary_shards
  • 网页排名算法 PageRank

PageRank,网页排名,又称网页级别,Google左侧排名或佩奇排名,是一种由搜索引擎根据网页之间相互的超链接计算的技,而作为网页排名的要素之一,以Google公司创辨人拉里·佩奇(Larry Page)之姓來命名。

  • PageRank 让链接来 [投票]

PageRank通过网络浩瀚的超链接開像来确定一个页面的等级。Google把从A页面到B页面的链接解释为A页面给B页面投票,Google根据投票来源(甚至来源的来源,即链接到A页面的页面)和投票目标的等级来决定新的等级。简单的说,一个高等级的页面可以使其他低等级页面的等级提升。

一个页面的「得票数」由所有链向它的页面的重要性来决定,到一个页面的超链接相当于对该页投一票。一个页面的PageRank是由所有链向它的页面([链入页面])的重要性经过递归算法得到的。一个有较多链入的页面会有较高的等级,相反如果一个页面没有任何链入页面,那么它没有等级。

  • PageRank算法

假设一个由4个页面组成的小团体:A,B,C和D。如果所有页面都链向A,那么A的PR(PageRank)值将是B,C及D的Pagerank总和。

PR(A)=PR(B)+PR(C)+PR(D)

JVM 虚拟机原理、Java 代码优化、秒杀系统相关推荐

  1. 深入JVM虚拟机(四) Java GC收集器

    转载自  深入JVM虚拟机(四) Java GC收集器 1 GC收集器 1.1 Serial串行收集器 串行收集器主要有两个特点:第一,它仅仅使用单线程进行垃圾回收:第二,它独占式的垃圾回收. 在串行 ...

  2. JVM优化原理—Java架构师必须要知晓的知识

    想要成为一名出色的Java架构师,必须要彻底了解Java的一个重要的特点那就JVM                                                           ...

  3. java虚拟机原理(java虚拟机的基本结构)

    虚拟机的分类 虚拟机大体上分为系统虚拟机和程序虚拟机: 如:大名鼎鼎的VMware就属于系统虚拟机,VMware是完全对物理计算机的仿真,提供一个可以运行完整操作系统的软件平台: 程序虚拟机的代表就是 ...

  4. Redis队列实现Java版秒杀系统(无脚本、可用于生产)

    本文系转载,原作者:控场的朴哥 原文地址:blog.csdn.net/weixin_43074462/article/details/103756536 写在前面 需求是做一个秒杀系统,比如大家来抢1 ...

  5. Redis 队列实现Java版秒杀系统(无脚本、可用于生产)

    写在前面 需求是做一个秒杀系统,比如大家来抢100台手机,先到先得. 查阅了网上很多用redis实现秒杀的demo(java语言),竟然没一个能用的!!! 有些是php的,没闲心研究了,现在说说为什么 ...

  6. 2019最新 Java商城秒杀系统的设计与实战视频教程(SpringBoot版)

    第一章 1-1课程整体介绍.mp4 1-2核心技术列表.mp4 1-3课程要求与收益.mp4 1-4系统的整体演示.mp4 https://www.jianshu.com/writer#/notebo ...

  7. JVM虚拟机原理深入解析,聪明人已经收藏了!

    前文 本文希望通过揭开一些 React 隐藏的技术细节, 来辅助对官方文档中某些概念的理解 读者可以将本文看做对官方文档的补充 行文方式我采用的是提问-解答的方式, 即先根据官方文档给出的使用规则, ...

  8. java转换成class文件_浅谈JVM编译原理-.java文件转变为.class文件的过程

    为什么需要编译? 我们平常写代码,有规范的命名方式,都能够看得懂,但是我们写的代码计算机是看不懂的,所以需要编译,也就是一个转换的过程,如下: 1.这个是咱们平时写的代码,就比较好理解,对人友好 2. ...

  9. 编译原理代码生成器java_浅谈JVM编译原理-.java文件转变为.class文件的过程

    为什么需要编译? 我们平常写代码,有规范的命名方式,都能够看得懂,但是我们写的代码计算机是看不懂的,所以需要编译,也就是一个转换的过程,如下: 1.这个是咱们平时写的代码,就比较好理解,对人友好 2. ...

最新文章

  1. html5搜索框美化,CSS美化的漂亮搜索框
  2. savexml php,PHP DOMDocument saveXML()用法及代码示例
  3. shell 判断字符串相等_编程小短文:Bash子字符串还在用==?试试=~性能瞬间飙升100倍...
  4. php报错提醒,php报错问题
  5. 句句真研—每日长难句打卡Day15
  6. 基础集群部署 - kubernetes-simple
  7. 笑傲江湖与三层交换、路由......
  8. STM32+L298N+PWM可调速小车(四驱)
  9. 子网掩码计算java,JAVA获取子网掩码源代码
  10. maven-replacer-plugin的使用
  11. Oracle 数据库表空间容量调整(表空间缩容脚本)脚本
  12. 数据驱动故障诊断方法汇总
  13. 【待更新】【UWB】UWB 学习、使用及 QCA平台移植实例
  14. 华为路由器旁挂引流实验(使用流策略)
  15. python计算长方体体积代码_编写程序,计算一个长方体的表面积和体积。
  16. 目标检测One-stage和Two-stage的区别
  17. 「Cpolar」看我如何实现公网远程控制Mac OS【使用mac自带VNC】
  18. 浏览器被劫持了 hao123
  19. 用计算机弹c哩c哩简谱数字,【扒谱】2020哔哩哔哩拜年祭部分数字谱
  20. Java单例破坏以及防止

热门文章

  1. 鼠标旋转视角,摄像机跟随围绕主角,人物移动
  2. 如何在电脑上使用计算机,字体如何安装到电脑里_怎么给电脑装字体-win7之家
  3. get request remoteAddr
  4. qq、微信登陆接入记录
  5. 程序员和上班族常用的在线工具网站
  6. 3dsmax导入Autocad立体图问题
  7. 计算机教案动作按钮,华兴小学信息技术五年级《PPT的动作按钮》教学设计
  8. 使用CAsyncSocket类进行网络编程
  9. 手把手教你撸Redis
  10. 给2019前端开发的你5个进阶建议~