当前位置: 首页 > news >正文

如何做网站编辑 沒技术推广引流要怎么做比较好

如何做网站编辑 沒技术,推广引流要怎么做比较好,现在市场网站建设怎么样,织梦做的网站快照被攻击一#xff1a;JVM 简介 JVM 是 Java Virtual Machine 的简称#xff0c;意为 Java 虚拟机#xff0c;虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。 常见的虚拟机#xff1a;JVM、VMwave、Virtual Box#xff0c;JVM 和其…一JVM 简介 JVM 是 Java Virtual Machine 的简称意为 Java 虚拟机虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。 常见的虚拟机JVM、VMwave、Virtual BoxJVM 和其他两个虚拟机的区别 VMwave 与 VirtualBox 是通过软件模拟物理 CPU 的指令集物理系统中会有很多的寄存器JVM 则是通过软件模拟 Java 字节码的指令集JVM 中只是主要保留了 PC 寄存器其他的寄存器都进行了裁剪。 JVM 是一台被定制过的现实当中不存在的计算机。 二 JVM 运行流程 程序在执行之前先要把 java 代码转换成字节码 class文件 JVM 首先需要把字节码通过一定的方式 类加载器 把文件加载到内存 运行时数据区 中而字节码文件是 JVM 的一套指令集规范并不能直接交个底层操作系统去执行因此需要特定的命令解析器 执行引擎 将字节码翻译成底层系统指令再交由 CPU 去执行而这个过程中需要调用其他语言的接口 本地库接口 来实现整个程序的功能这就是这 4 个主要组成部分的职责与功能 总结来看 JVM 主要通过分为以下 4 个部分来执行 Java 程序的它们分别是 类加载器ClassLoader运行时数据区Runtime Data Area执行引擎Execution Engine本地库接口Native Interface 2.1 JVM 运行时数据区 JVM 运行时数据区域也叫内存布局但需要注意的是它和 Java 内存模型 Java Memory Model简称 JMM 完全不同属于完全不同的两个概念它由以下 5 大部分组成 2.1.1 堆线程共享 堆的作用程序中创建的所有对象都在保存在堆中。 堆里面分为两个区域新生代和老生代新生代放新建的对象当经过一定 GC 次数之后还存活的对象会放入老生代。新生代还有 3 个区域一个 Endn 两个 Survivo S0/S1。 垃圾回收的时候会将 Endn 中存活的对象放到一个未使用的 Survivor 中并把当前的 Endn 和正在使用的 Survivor 清楚掉。 JDK 8 中将字符串常量池移动到了堆中运行时常量池是方法区的一部分存放字面量与符号引用。 字面量 : 字符串、final常量、基本数据类型的值。符号引用 : 类和结构的完全限定名、字段的名称和描述符、方法的名称和描述符。 2.1.2 Java 虚拟机栈线程私有 Java 虚拟机栈的作用Java 虚拟机栈的生命周期和线程相同Java 虚拟机栈描述的是 Java 方法执行的内存模型每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。咱们常说的堆内存、栈内存中栈内存指的就是虚拟机栈。 Java 虚拟机栈中包含了以下 4 部分 局部变量表 存放了编译器可知的各种基本数据类型、对象引用。局部变量表所需的内存空间在编译期间完成分配。简单来说就是存放方法参数和局部变量。操作栈每个方法会生成一个先进后出的操作栈。动态链接指向运行时常量池的方法方法返回地址PC 寄存器的地址。 什么是线程私有? 由于 JVM 的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现因此在任何一个确定的时刻一个处理器都只会执行一条线程中的指令。因此为了切换线程后能恢复到正确的执行位置每条线程都需要独立的程序计数器各条线程之间计数器互不影响独立存储。我们就把类似这类区域称之为线程私有的内存。 2.1.3 本地方法栈线程私有 本地方法栈和虚拟机栈类似只不过 Java 虚拟机栈是给 JVM 使用的而本地方法栈是给本地方法使用的。 2.1.4 程序计数器线程私有 程序计数器的作用用来记录当前线程执行的行号。 程序计数器是一块比较小的内存空间可以看做是当前线程所执行的字节码的行号指示器。如果当前线程正在执行的是一个 Java 方法这个计数器记录的是正在执行的虚拟机字节码指令的地址如果正在执行的是一个 Native 方法这个计数器值为空。 程序计数器内存区域是唯一一个在 JVM 规范中没有规定任何 OOM 情况的区域 2.1.5 方法区线程共享 方法区的作用用来存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据的方法区在 JDK 7 时此区域叫做永久代JDK 8 中叫做元空间。 2.2 JVM 类加载 2.2.1 类加载过程 和程序员关系最密切的就是类加载的过程了所以接下来我们来看下类加载的执行流程对于一个类来说它的生命周期是这样的 其中前 5 步是固定的顺序并且也是类加载的过程其中中间的 3 步我们都属于连接所以对于类加载来说总共分为以下几个步骤 加载连接 验证准备解析 初始化 下面我们分别来看每个步骤的具体执行内容。 2.2.1.1 加载 在加载阶段Java 虚拟机需要完成以下三件事情 通过一个类的全限定名来获取定义此类的二进制字节流。将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。在内存中生成一个代表这个类的 java.lang.Class 对象作为方法区这个类的各种数据的访问入口。 2.2.1.2 验证 验证是连接阶段的第一步这一阶段的目的是确保 Class 文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求保证这些信息被当作代码运行后不会危害虚拟机自身的安全。 验证选项 文件格式验证字节码验证符号引用验证… 2.2.1.3 准备 准备阶段是正式为类中定义的变量 即静态变量被 static 修饰的变量 分配内存并设置类变量初始值的阶段。 比如此时有这样一行代码 public static int value 123;它是初始化 value 的 int 值为 0而非 123。 2.2.1.4 解析 解析阶段是 Java 虚拟机将常量池内的符号引用替换为直接引用的过程也就是初始化常量的过程。 2.2.1.5 初始化 初始化阶段Java 虚拟机真正开始执行类中编写的 Java 程序代码将主导权移交给应用程序。初始化阶段就是执行类构造器方法的过程。 2.2.2 双亲委派模型 提到类加载机制不得不提的一个概念就是“双亲委派模型”。 站在 Java 虚拟机的角度来看只存在两种不同的类加载器一种是启动类加载器这个类加载器使用 C 语言实现是虚拟机自身的一部分另外一种就是其他所有的类加载器这些类加载器都由 Java 语言实现独立存在于虚拟机外部。 站在 Java 开发人员的角度来看类加载器就应当划分得更细致一 些。自 JDK 1.2 以来Java 一直保持着三层类加载器、双亲委派的类加载架构器。 2.2.2.1 什么是双亲委派模型 如果一个类加载器收到了类加载的请求它首先不会自己去尝试加载这个类而是把这个请求委派给父类加载器去完成每一个层次的类加载器都是如此因此所有的加载请求最终都应该传送到最顶层的启动类加载器中只有当父加载器反馈自己无法完成这个加载请求时子加载器才会尝试自己去完成加载。 启动类加载器加载 JDK 中 lib 目录中 Java 的核心类库即$JAVA_HOME/lib目录。 扩展类加载器。加载 lib/ext 目录下的类。应用程序类加载器加载我们写的应用程序。自定义类加载器根据自己的需求定制类加载器。 2.2.2.2 双亲委派模型的优点 避免重复加载类比如 A 类和 B 类都有一个父类 C 类那么当 A 启动时就会将 C 类加载起来那么在 B 类进行加载时就不需要在重复加载 C 类了。安全性使用双亲委派模型也可以保证了 Java 的核心 API 不被篡改如果没有使用双亲委派模型而是每个类加载器加载自己的话就会出现一些问题比如我们编写一个称为 java.lang.Object 类的话那么程序运行的时候系统就会出现多个不同的 Object 类而有些 Object 类又是用户自己提供的因此安全性就不能得到保证了。 2.2.2.3 破坏双亲委派模型 亲委派模型虽然有其优点但在某些情况下也存在一定的问题比如 Java 中 SPI 机制中的 JDBC 实现。 JDBC 的 Driver 接口定义在 JDK 中其实现由各个数据库的服务商来提供比如 MySQL 驱动包。我们先来看下 JDBC 的核心使用代码 public class JdbcTest {public static void main(String[] args){Connection connection null;try {connection DriverManager.getConnection(jdbc:mysql://127.0.0.1:3306/test, root,awakeyo);} catch (SQLException e) {e.printStackTrace();}System.out.println(connection.getClass().getClassLoader());System.out.println(Thread.currentThread().getContextClassLoader());System.out.println(Connection.class.getClassLoader());} }然后我们进入 DriverManager 的源码类就会发现它是存在系统的 rt.jar 中的如下图所示 由双亲委派模型的加载流程可知 rt.jar 是有顶级父类 Bootstrap ClassLoader 加载的如下图所示 而当我们进入它的 getConnection 源码是却发现它在调用具体的类实现时使用的是子类加载器来加载具体的数据库数据库包源码如下 CallerSensitive public static Connection getConnection(String url, java.util.Properties info) throws SQLException { return (getConnection(url, info, Reflection.getCallerClass())); } private static Connection getConnection(String url, java.util.Properties info, Class? caller) throws SQLException {ClassLoader callerCL caller ! null ? caller.getClassLoader() : null;synchronized(DriverManager.class) {// synchronize loading of the correct classloader.if (callerCL null) {//获取线程上下为类加载器callerCL Thread.currentThread().getContextClassLoader();}}if(url null) {throw new SQLException(The url cannot be null, 08001);}println(DriverManager.getConnection(\ url \));SQLException reason null;for(DriverInfo aDriver : registeredDrivers) {// isDriverAllowed 对于 mysql 连接 jar 进行加载if(isDriverAllowed(aDriver.driver, callerCL)) {try {println( trying aDriver.driver.getClass().getName());Connection con aDriver.driver.connect(url, info);if (con ! null) {// Success!println(getConnection returning aDriver.driver.getClass().getName());return (con);}} catch (SQLException ex) {if (reason null) {reason ex;}}} else {println( skipping: aDriver.getClass().getName());}}if (reason ! null) {println(getConnection failed: reason);throw reason;}println(getConnection: no suitable driver found for url);throw new SQLException(No suitable driver found for url, 08001);}这样一来就破坏了双亲委派模型因为 DriverManager 位于 rt.jar 包由 BootStrap 类加载器加载而其 Driver 接口的实现类是位于服务商提供的 Jar 包中是由子类加载器来加载的这样就破坏了双亲委派模型了。它的交互流程图如下所示 2.3 垃圾回收相关 上面讲了 Java 运行时内存的各个区域。对于程序计数器、虚拟机栈、本地方法栈这三部分区域而言其生命周期与相关线程有关随线程而生随线程而灭。并且这三个区域的内存分配与回收具有确定性因为当方法结束或者线程结束时内存就自然跟着线程回收了。因此我们本节课所讲的有关内存分配和回收关注的为 Java 堆与方法区这两个区域。 Java堆中存放着几乎所有的对象实例垃圾回收器在对堆进行垃圾回收前首先要判断这些对象哪些还存活哪些已经死去。标记和判断对象是否已死有如下几种算法 2.3.1 引用计数算法 引用计数描述的算法为:给对象增加一个引用计数器每当有一个地方引用它时计数器就 1当引用失效时计数器就 -1任何时刻计数器为 0 的对象就是不能再被使用的即对象已死。 引用计数法实现简单判定效率也比较高在大部分情况下都是一个不错的算法。比如 Python 语言就采用引用计数法进行内存管理。但是在主流的 JVM 中没有选用引用计数法来管理内存最主要的原因就是引用计数法无法解决对象的循环引用问题 2.3.2 可达性分析算法 Java 并不采用引用计数法来判断对象是否已死而采用可达性分析来判断对象是 否存活 此算法的核心思想为 : 通过一系列称为GC Roots的对象作为起始点从这些节点开始向下搜索搜索走过的路径称之为引用链当一个对象到 GC Roots 没有任何的引用链相连时 ( 从 GC Roots 到这个对象不可达 ) 时证明此对象是不可用的。以下图为例 对象 Object5-Object7 之间虽然彼此还有关联但是它们到 GC Roots 是不可达的因此他们会被判定为可回收对象。 在Java语言中可作为 GC Roots 的对象包含下面几种: 虚拟机栈中引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象本地方法栈中引用的对象。 从上面我们可以看出“引用”的功能除了最早我们使用它引用来查找对象现在我们还可以使用“引用”来判断死亡对象了。所以在 JDK1.2 时Java 对引用的概念做了扩充将引用分为强引用、软引用、弱引用)和虚引用四种这四种引用的强度依次递减。 强引用 : 强引用指的是在程序代码之中普遍存在的类似于Object obj new Object()这类的引用只要强引用还存在垃圾回收器永远不会回收掉被引用的对象实例。软引用 : 软引用是用来描述一些还有用但是不是必须的对象。对于软引用关联着的对象在系统将要发生内存溢出之前会把这些对象列入回收范围之中进行第二次回收。如果这次回收还是没有足够的内存才会抛出内存溢出异常。弱引用 : 弱引用也是用来描述非必需对象的。但是它的强度要弱于软引用。被弱引用关联的对象只能生存到下一次垃圾回收发生之前。当垃圾回收器开始进行工作时无论当前内容是否够用都会回收掉只被弱引用关联的对象。虚引用 : 虚引用也被称为幽灵引用或者幻影引用它是最弱的一种引用关系。一个对象是否有虚引用的存在完全不会对其生存时间构成影响也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。 2.3.3 垃圾回收算法 通过上面的学习我们可以将死亡对象标记出来了标记出来之后我们就可以进行垃圾回收操作了在正式学习垃圾收集器之前我们先看下垃圾回收机器使用的几种算法这些算法是垃圾收集器的指导思想。 2.3.3.1 标记-清除算法 标记-清除算法是最基础的收集算法。算法分为标记和清除两个阶段 : 首先标记出所有需要回收的对象在标记完成后统一回收所有被标记的对象。后续的收集算法都是基于这种思路并对其不足加以改进而已。 标记-清除算法的不足主要有两个 : 效率问题 : 标记和清除这两个过程的效率都不高空间问题 : 标记清除后会产生大量不连续的内存碎片空间碎片太多可能会导致以后在程序运行中需要分配较大对象时无法找到足够连续内存而不得不提前触发另一次垃圾收集。 2.3.3.2 复制算法 复制算法是为了解决标记-清理的效率问题。它将可用内存按容量划分为大小相等的两块每次只使用其中的一块。当这块内存需要进行垃圾回收时会将此区域还存活着的对象复制到另一块上面然后再把已经使用过的内存区域一次清理掉。这样做的好处是每次都是对整个半区进行内存回收内存分配时也就不需要考虑内存碎片等复杂情况只需要移动堆顶指针按顺序分配即可。此算法实现简单运行高效。算法的执行流程如下图 : 新生代中 98% 的对象都是朝生夕死的所以并不需要按照 1 : 1 的比例来划分内存空间而是将内存分为一块较大的 Eden ( 伊甸园 ) 空间和两块较小的 Survivor ( 幸存者 ) 空间每次使用 Eden 和其中一块 Survivor。当回收时将 Eden 和 Survivor 中还存活的对象一次性复制到另一块 Survivor 空间上最后清理掉 Eden 和刚才用过的 Survivor 空间。当 Survivor 空间不够用时需要依赖其他内存进行分配担保。 HotSpot 默认 Eden 与 Survivor 的大小比例是 8 : 1也就是说 Eden:Survivor From : Survivor To 8:1:1 两个 Survivor 区域一个称为 From 区另一个称为 To 区域 。所以每次新生代可用内存空间为整个新生代容量的 90%,而剩下的 10% 用来存放回收后存活的对象。 2.3.3.3 标记-整理算法 复制收集算法在对象存活率较高时会进行比较多的复制操作效率会变低。因此在老年代一般不能使用复制算法。 针对老年代的特点提出了一种称之为标记-整理算法。标记过程仍与标记-清除过程一致但后续步骤不是直接对可回收对象进行清理而是让所有存活对象都向一端移动然后直接清理掉端边界以外的内存。流程图如下: 2.3.3.4 分代算法 分代算法和上面讲的 3 种算法不同分代算法是通过区域划分实现不同区域和不同的垃圾回收策略从而实现更好的垃圾回收。这就好比中国的一国两制方针一样对于不同的情况和地域设置更符合当地的规则从而实现更好的管理这就时分代算法的设计思想。 当前 JVM 垃圾收集都采用的是分代收集算法这个算法并没有新思想只是根据对象存活周期的不同将内存划分为几块。一般是把 Java 堆分为新生代和老年代。在新生代中每次垃圾回收都有大批对象死去只有少量存活因此我们采用复制算法而老年代中对象存活率高、没有额外空间对它进行分配担保就必须采用标记-清理或者标记-整理算法。 哪些对象会进入新生代哪些对象会进入老年代 新生代一般创建的对象都会进入新生代老年代大对象和经历了 N 次一般情况默认是 15 次垃圾回收依然存活下来的对象会从新生代移动到老年代。 2.3.4 垃圾收集器 如果说上面我们讲的收集算法是内存回收的方法论那么垃圾收集器就是内存回收的具体实现。 垃圾收集器的作用垃圾收集器是为了保证程序能够正常、持久运行的一种技术它是将程序中不用的死亡对象也就是垃圾对象进行清除从而保证了新对象能够正常申请到内存空间以下这些收集器是 HotSpot 虚拟机随着不同版本推出的重要的垃圾收集器 上图展示了 7 种作用于不同分代的收集器如果两个收集器之间存在连线就说明他们之间可以搭配使用。所处的区域表示它是属于新生代收集器还是老年代收集器。在讲具体的收集器之前我们先来明确三个概念: 并行(Parallel) : 指多条垃圾收集线程并行工作用户线程仍处于等待状态并发(Concurrent) :指用户线程与垃圾收集线程同时执行 ( 不一定并行可能会交替执行 ) 用户程序继续运行而垃圾收集程序在另外一个 CPU 上。吞吐量:就是 CPU 用于运行用户代码的时间与 CPU 总消耗时间的比值。 吞吐量 运行用户代码时间 / 运行用户代码时间 垃圾收集时间 例如虚拟机总共运行了 100 分钟其中垃圾收集花掉 1 分钟那吞吐量就是 99%。 2.3.4.1 为什么会有这么多垃圾收集器 自从有了 Java 语言就有了垃圾收集器这么多垃圾收集器其实是历史发展的产物。最早的垃圾收集器为 Serial也就是串行执行的垃圾收集器Serial Old 为串行的老年代收集器而随着时间的发展为了提升更高的性能于是有了 Serial 多线程版的垃圾收集器 ParNew。后来人们想要更高吞吐量的垃圾收集器于是就有了吞吐量优先的垃圾收集器 Parallel Scavenge 吞吐量优先的新生代垃圾收集器 和 Parallel Old 吞吐量优先的老年代垃圾收集器 。随着技术的发展后来又有了 CMS Concurrent Mark Sweep 垃圾收集器CMS 可以兼顾吞吐量和以获取最短回收停顿时间为目标的收集器在 JDK 1.8 包含 之前 BS 系统的主流垃圾收集器而在 JDK 1.8 之后出现了第一个既不完全属于新生代也不完全属于老年代的垃圾收集器 G1G1 提供了基本不需要停止程序就可以收集垃圾的技术. 2.4总结 一个对象的一生一个对象的一生我是一个普通的 Java 对象我出生在 Eden 区在 Eden 区我还看到和我长的很像的小兄弟我们在 Eden 区中玩了挺长时间。有一天 Eden 区中的人实在是太多了我就被迫去了 Survivor 区的 “From” 区S0 区自从去了 Survivor 区我就开始漂了有时候在 Survivor 的 “From” 区有时候在 Survivor 的 “To” 区S1 区居无定所。直到我 18 岁的时候爸爸说我成人了该去社会上闯闯了。于是我就去了年老代那边年老代里人很多并且年龄都挺大的我在这里也认识了很多人。在老年代里我生活了很多年 每次 GC 加一岁 然后被回收了。 三JMM JVM 定义了一种 Java 内存模型 ( Java Memory Model,JMM ) 来屏蔽掉各种硬件和操作系统的内存访问差异以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。在此之前C/C直接使用物理硬件和操作系统的内存模型因此会由于不同平台下的内存模型的差异有可能导致程序在一套平台上并发完全正常而在另一套平台上并发访问经常出错。 3.1 主内存与工作内存 Java 内存模型的主要目标是定义程序中各个变量的访问规则即在 JVM 中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量包括实例字段、静态字段和构成数组对象的元素但不包括局部变量和方法参数因为后两者是线程私有的不会被线程共享。 Java 内存模型规定了所有的变量都存储在主内存中。每条线程还有自己的工作内存线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝线程对变量的所有操作(读取、赋值等)都必须在工作内存进行而不能直接读写主内存中的变量。不同的线程之间也无法直接访问对方工作内存中的变量线程间变量值的传递均需要通过主内存来完成。线程、主内存、工作内存三者的交互关系如下所示 : 3.2 内存间交互操作 关于主内存与工作内存之间的具体交互协议即一个变量如何从主内存中拷贝到工作内存、如何从工作内存同步回主内存之类的实现细节Java 内存模型中定义了如下 8 种操作来完成。JVM 实现时必须保证下面提及的每一种操作的原子的、不可再分的。 lock ( 锁定 ) : 作用于主内存的变量它把一个变量标识为一条线程独占的状态unlock ( 解锁 ) : 作用于主内存的变量它把一个处于锁定状态的变量释放出来释放后的变量才可以被其他线程锁定。read ( 读取 ) : 作用于主内存的变量它把一个变量的值从主内存传输到线程的工作内存中以便随后的 load 动作使用。load ( 载入 ) : 作用于工作内存的变量它把 read 操作从主内存中得到的变量值放入工作内存的变量副本中。use ( 使用 ) : 作用于工作内存的变量它把工作内存中一个变量的值传递给执行引擎。assign ( 赋值 ) : 作用于工作内存的变量它把一个从执行引擎接收到的值赋给工作内存的变量。store ( 存储 ) : 作用于工作内存的变量它把工作内存中一个变量的值传送到主内存中以便后续的 write 操作使用。write ( 写入 ) : 作用于主内存的变量它把 store 操作从工作内存中得到的变量的值放入主内存的变量中。 Java 内存模型的三大特性 : 原子性 :由 Java 内存模型来直接保证的原子性变量操作包括 read、load、assign、use、store 和 read。大致可以认为基本数据类型的访问读写是具备原子性的。如若需要更大范围的原子性需要 synchronized 关键字约束。( 即一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断要么就都不执行 )可见性 : 可见性是指当一个线程修改了共享变量的值其他线程能够立即得知这个修改。volatile、synchronized、final 三个关键字可以实现可见性。有序性 :如果在本线程内观察所有的操作都是有序的如果在线程中观察另外一个线程所有的操作都是无序的。前半句是指线程内表现为串行后半句是指指令重排序和工作内存与主内存同步延迟现象。 Java 内存模型具备一些先天的“有序性”即不需要通过任何手段就能够得到保证的有序性这个通常也称为 happens-before 原则。如果两个操作的执行次序无法从 happens-before 原则推导出来那么它们就不能保证它们的有序性虚拟机可以随意地对它们进行重排序。 下面就来具体介绍下 happens-before 原则 先行发生原则 程序次序规则一个线程内按照代码顺序书写在前面的操作先行发生于书写在后面的操作锁定规则一个 unLock 操作先行发生于后面对同一个锁的 lock 操作volatile 变量规则对一个变量的写操作先行发生于后面对这个变量的读操作传递规则如果操作 A 先行发生于操作 B而操作 B 又先行发生于操作 C则可以得出操作 A 先行发生于操作 C线程启动规则Thread 对象的 start() 方法先行发生于此线程的每个一个动作线程中断规则对线程 interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生线程终结规则线程中所有的操作都先行发生于线程的终止检测我们可以通过 Thread.join() 方法结束、Thread.isAlive() 的返回值手段检测到线程已经终止执行对象终结规则一个对象的初始化完成先行发生于他的 finalize() 方法的开始也就是说要想并发程序正确地执行必须要保证原子性、可见性以及有序性。只要有一个没有被保证就有可能会导致程序运行不正确。 3.3 volatile 型变量的特殊规则 关键字 volatile 可以说是JVM提供的最轻量级的同步机制但是它并不容易完全被正确理解和使用。JVM 内存模型对 volatile 专门定义了一些特殊的访问规则当一个变量定义为 volatile 之后它将具备两种特性。 3.3.1 保证此变量对所有线程的可见性 这里的可见性是指 : 当一条线程修改了这个变量的值新值对于其他线程来说是可以立即得知的。而普通变量做不到这一点普通变量的值在线程间传递均需要通过主内存来完成。例如:线程 A 修改一个普通变量的值然后向主内存进行回写另外一条线程 B 在线程 A 回写完成之后再从主内存进行读取操作新值才会对线程 B 可见。 关于 volatile 变量的可见性经常会被开发人员误解。volatile 变量在各个线程中是一致的但是 volatile 变量的运算在并发下一样是不安全的。原因在于 Java 里面的运算并非原子操作。 3.3.2 使用 volatile 禁止指令重排序 普通的变量仅仅会保证在该方法的执行过程中所有依赖赋值结果的地方都能获取到正确的结果而不能保证变量赋值操作的顺序和程序代码中执行的顺序一致。 volatile 关键字禁止指令重排序有两层意思 当程序执行到 volatile 变量的读操作或者写操作时在其前面的操作的更改肯定全部已经进行且结果已经对后面的操作可见在其后面的操作肯定还没有进行在进行指令优化时不能将在对 volatile 变量访问的语句放在其后面执行也不能把 volatile 变量后面的语句放到其前面执行。 举个简单的例子 //x、y为非volatile变量 //flag为volatile变量 x 2; //语句1 y 0; //语句2 flag true; //语句3 x 4; //语句4 y -1; //语句5由于 flag 变量为 volatile 变量那么在进行指令重排序的过程的时候不会将语句 3 放到语句 1、语句 2 前面也不会将语句3放到语句 4、语句 5 后面。但是要注意语句1和语句2的顺序、语句 4 和语句 5 的顺序是不作任何保证的。 并且 volatile 关键字能保证执行到语句 3 时语句 1 和语句 2 必定是执行完毕了的且语句 1 和语句 2 的执行结果对语句 3、语句 4、语句 5 是可见的。
文章转载自:
http://www.morning.dbfj.cn.gov.cn.dbfj.cn
http://www.morning.kngx.cn.gov.cn.kngx.cn
http://www.morning.gkfwp.cn.gov.cn.gkfwp.cn
http://www.morning.huarma.com.gov.cn.huarma.com
http://www.morning.rfwqt.cn.gov.cn.rfwqt.cn
http://www.morning.zbnkt.cn.gov.cn.zbnkt.cn
http://www.morning.rpzqk.cn.gov.cn.rpzqk.cn
http://www.morning.nqlnd.cn.gov.cn.nqlnd.cn
http://www.morning.trwkz.cn.gov.cn.trwkz.cn
http://www.morning.bktzr.cn.gov.cn.bktzr.cn
http://www.morning.routalr.cn.gov.cn.routalr.cn
http://www.morning.hmjasw.com.gov.cn.hmjasw.com
http://www.morning.chgmm.cn.gov.cn.chgmm.cn
http://www.morning.gynkr.cn.gov.cn.gynkr.cn
http://www.morning.mhlkc.cn.gov.cn.mhlkc.cn
http://www.morning.nfcxq.cn.gov.cn.nfcxq.cn
http://www.morning.kkrnm.cn.gov.cn.kkrnm.cn
http://www.morning.mbprq.cn.gov.cn.mbprq.cn
http://www.morning.rdwm.cn.gov.cn.rdwm.cn
http://www.morning.ywpwg.cn.gov.cn.ywpwg.cn
http://www.morning.zhffz.cn.gov.cn.zhffz.cn
http://www.morning.kjjbz.cn.gov.cn.kjjbz.cn
http://www.morning.jpbpc.cn.gov.cn.jpbpc.cn
http://www.morning.c7630.cn.gov.cn.c7630.cn
http://www.morning.ndynz.cn.gov.cn.ndynz.cn
http://www.morning.zzfqn.cn.gov.cn.zzfqn.cn
http://www.morning.nckjk.cn.gov.cn.nckjk.cn
http://www.morning.cwlxs.cn.gov.cn.cwlxs.cn
http://www.morning.qqpg.cn.gov.cn.qqpg.cn
http://www.morning.rmqlf.cn.gov.cn.rmqlf.cn
http://www.morning.wpcfm.cn.gov.cn.wpcfm.cn
http://www.morning.mqghs.cn.gov.cn.mqghs.cn
http://www.morning.rjrnx.cn.gov.cn.rjrnx.cn
http://www.morning.nmngq.cn.gov.cn.nmngq.cn
http://www.morning.cjqqj.cn.gov.cn.cjqqj.cn
http://www.morning.lwcqh.cn.gov.cn.lwcqh.cn
http://www.morning.gklxm.cn.gov.cn.gklxm.cn
http://www.morning.xsbhg.cn.gov.cn.xsbhg.cn
http://www.morning.cjmmt.cn.gov.cn.cjmmt.cn
http://www.morning.nnqrb.cn.gov.cn.nnqrb.cn
http://www.morning.mbpfk.cn.gov.cn.mbpfk.cn
http://www.morning.clbsd.cn.gov.cn.clbsd.cn
http://www.morning.dmzzt.cn.gov.cn.dmzzt.cn
http://www.morning.bxch.cn.gov.cn.bxch.cn
http://www.morning.mkfhx.cn.gov.cn.mkfhx.cn
http://www.morning.dhtdl.cn.gov.cn.dhtdl.cn
http://www.morning.zlnyk.cn.gov.cn.zlnyk.cn
http://www.morning.nyqm.cn.gov.cn.nyqm.cn
http://www.morning.xxrgt.cn.gov.cn.xxrgt.cn
http://www.morning.ctqlq.cn.gov.cn.ctqlq.cn
http://www.morning.nwtmy.cn.gov.cn.nwtmy.cn
http://www.morning.ghlyy.cn.gov.cn.ghlyy.cn
http://www.morning.mpmtz.cn.gov.cn.mpmtz.cn
http://www.morning.qcymf.cn.gov.cn.qcymf.cn
http://www.morning.zdwjg.cn.gov.cn.zdwjg.cn
http://www.morning.mxcgf.cn.gov.cn.mxcgf.cn
http://www.morning.rrcxs.cn.gov.cn.rrcxs.cn
http://www.morning.kkhf.cn.gov.cn.kkhf.cn
http://www.morning.pzjrm.cn.gov.cn.pzjrm.cn
http://www.morning.dbqcw.com.gov.cn.dbqcw.com
http://www.morning.kgnnc.cn.gov.cn.kgnnc.cn
http://www.morning.jxltk.cn.gov.cn.jxltk.cn
http://www.morning.osshjj.cn.gov.cn.osshjj.cn
http://www.morning.rgsnk.cn.gov.cn.rgsnk.cn
http://www.morning.jpgfx.cn.gov.cn.jpgfx.cn
http://www.morning.zdtfr.cn.gov.cn.zdtfr.cn
http://www.morning.nkjjp.cn.gov.cn.nkjjp.cn
http://www.morning.ykrss.cn.gov.cn.ykrss.cn
http://www.morning.qllcm.cn.gov.cn.qllcm.cn
http://www.morning.cbynh.cn.gov.cn.cbynh.cn
http://www.morning.mdgpp.cn.gov.cn.mdgpp.cn
http://www.morning.qckwj.cn.gov.cn.qckwj.cn
http://www.morning.pznqt.cn.gov.cn.pznqt.cn
http://www.morning.smj78.cn.gov.cn.smj78.cn
http://www.morning.gbhsz.cn.gov.cn.gbhsz.cn
http://www.morning.rsszk.cn.gov.cn.rsszk.cn
http://www.morning.rdymd.cn.gov.cn.rdymd.cn
http://www.morning.gwdmj.cn.gov.cn.gwdmj.cn
http://www.morning.sxcwc.cn.gov.cn.sxcwc.cn
http://www.morning.qsfys.cn.gov.cn.qsfys.cn
http://www.tj-hxxt.cn/news/269948.html

相关文章:

  • 精品网站建设费用 找磐石网络一流企业网站制作价格
  • 虚拟货币交易网站建设对网站建设心得
  • 哪里有营销型网站网页设计制作实训报告模板
  • 潍坊专业网站建设价格青海做高端网站建设的公司
  • 免费空间asp网站保定网站seo哪家公司好
  • 博物馆文化网站建设仿v电影wordpress
  • 博客网站seozend studio 网站开发
  • 莱芜网站建设资情况介绍网站建设课程 考核目的
  • 建筑参考网站如何做旅游休闲网站
  • 咖啡网站设计模板用asp做网站怎么布局
  • 网站备案年审微信crm客户管理系统
  • c2c代表网站是什么网站类型分类
  • 重庆自助建站模板建设网站的收费
  • 做网站需要哪几个板块酒店网站建设流程图
  • 电商网站建设基本流程做的好的茶叶网站好
  • 短租网网站开发 项目背景缘震网络网站建设之f套餐
  • 做海报的网站有哪些内容湖北省疾病预防控制中心官方网站
  • 北京市优化网站jsp 哪些网站
  • 个人网站是请人做还是自己编写好wordpress仿虎嗅
  • 网站设计基础知识伪静态 wordpress
  • 北京中小型网站建设肃北蒙古族自治县建设局网站
  • 做网站最好用的软件如何做h5
  • 佛山专业网站建设哪家好软件推广的渠道是哪里找的
  • 做网站是要写代码的吗篮球网站设计
  • 网站备案可以国际域名小程序开发教程文档
  • php网站制作报价ps案例教程网站
  • 朔州网站设计公司网站开发公司怎么找客户
  • 制作网站 公司少儿编程网课平台哪个好
  • 湖南做网站 尖端磐石网络上线了做网站多少钱
  • 只做鱼网站现在搭建一个网站需要多少钱