本地线程

总结:无耻的收藏一篇很好的JVM文章

随声附和 提交于 2019-12-04 10:38:41
JVM(Java虚拟机)简单来说就是运行Java代码的解释器,作为螺丝钉程序员JVM其实了解下就差不多啦,不懂JVM内部细节照样能写出优质的代码!但是一到造火箭、飞机的场景(面试)不懂JVM的你,会被面试官虐的体无完肤,本期内容列举常见的JVM面试题: 说一JVM的内存模型是什么样子的? 什么时候对象可以被收回? 常见的垃圾回收器算法有哪些,各有什么优劣? 什么时候对象会进入老年代? 什么是空间分配担保策略? 如何优化减少Full GC? 面对这一大波JVM面试题,你真的Hold住吗? JVM的内存模型是什么样子的? JVM内存模型可以大致可划分为 线程私有区域 和 共享区域 ,线程私有区域由虚拟机栈、本地方法栈、程序计数器组成,而共享区域由堆、元数据空间(方法区)组成。 再有人问你JVM的内存模型就回想下上面的图,但是知道JVM的内存模型的样子还是不行的,还要知道他们分别干什么的。 虚拟机栈/本地方法栈 当你碰到过StackOverflowException这个异常的时候,有没有思考下为什么会出现这样的异常呢?答案就在虚拟机栈中,JVM会为每个方法生成 栈帧 然后将 栈帧 压入虚拟机栈中。 举个粟子:假设JVM参数-Xss设置为1m,如果某个方法里面创建一个128kb的数组,那这个方法在同一个线程中只能递归4次

JVM 内存模型

纵饮孤独 提交于 2019-12-04 08:04:24
Java内存模型(Java Memory Model ,JMM)是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。 简要言之,jmm是jvm的一种规范,定义了jvm的内存模型。它屏蔽了各种硬件和操作系统的访问差异,不像 c那样直接访问硬件内存,相对安全很多,它的主要目的是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题。可以保证并发编程场景中的原子性、可见性和有序性。 五大内存区域: 程序计数器(program counter register):线程私有, 程序计数器是很小的一块内存空间,可以认作为当前线程的行号指示器。 在cpu的一个核心 在某一既定时刻只会执行一条线程中的指令,然而线程中会存在多个指令,为了cpu处理不同线程指令时,线程切换回来可以定位(或者时恢复)到正确的执行位置,那么这个时候就需要每个线程都做一个独立的记号,这个记号就叫做程序计数器。不同线程的程序计数器是独立存储,互不干扰的。 当线程执行某个java方法时,程序计数器记录的是虚拟机自己吗指令的地址。如果是native方法(底层方法),计数器为空。 程序计数器所处内存区域,是虚拟机规范中唯一没有OutOfMemoryError的区域。 为方便理解

JAVA虚拟机起步-虚拟机调优

喜夏-厌秋 提交于 2019-12-04 07:31:19
JAVA虚拟机起步OutOfMemory问题解决记录。 问题: JAVA虚拟机报错 # java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate. Out of swap space? # # Internal Error (allocation.cpp:117), pid=26666, tid=2409851824 # Error: ChunkPool::allocate 解决办法: 平衡每个线程需要的内存存储器的堆栈大小,在程序内部控制线程总数量。 理论: JVM线程堆栈 应用程序中的每个线程都需要内存来存储器堆栈(用于在调用函数时持有局部变量并维护状态的内存区域)。每个 Java 线程都需要堆栈空间来运行。 根据实现的不同,Java 线程可以分为本机线程和 Java 堆栈。除了堆栈空间,每个线程还需要为线程本地存储(thread-local storage)和内部数据结构提供一些本机内存。 JVM堆栈大小 -Xss 128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆 栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。 在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一 个进程内的线程数还是有限制的,不能无限生成,经验值在3000

分布式系统笔记

邮差的信 提交于 2019-12-04 07:10:53
1.1.1什么是分布式系统 《分布式系统原理与范型》一书中是这样定义分布式系统的: “分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”。 这里面包含了2个含义: 硬件独立; 软件统一。 1.2.1什么是线程 线程是程序执行流的最小单位。一个标准的线程由线程ID、当前指令指针(PC)、寄存器集合和堆栈组成。 线程拥有三种基本状态: 就绪; 阻塞; 运行。 1.2.3Java编程语言中的线程对象 Java中有两种创建Thread实例的方式: 使用Runnable对象 继承Thread 1.3.2网络I/O模型的演进 同步和异步描述的是用户线程与内核的交互方式: 同步是指用户线程发起I/O请求后需要等待或者轮询内核I/O操作完成后才能继续执行; 同步是指用户线程发起I/O请求后仍继续执行,当内核I/O操作完成后会通知用户线程,或者调用用户线程注册的回调函数。 阻塞和非阻塞描述的是用户线程调用内核I/O操作的方式: 阻塞是指I/O操作需要彻底完成后才返回到用户空间; 非阻塞是指I/O操作被调用后立即返回给用户一个状态值,无须等到I/O操作彻底完成。 一个I/O操作其实被分成了两个步骤:发起I/O请求和实际的I/O操作。 阻塞I/O和非阻塞I/O的区别在于第一步,发起I/O请求是否会被阻塞。 同步I/O和异步I/O的区别在于第二步是否阻塞,如果实际的I

Thread中的start和run方法的区别

拟墨画扇 提交于 2019-12-04 06:54:19
面试必问,面试必问,面试必问!别问我为什么知道~~ 总结 run()只是Thread类的一个普通方法,调用run()并不会新建一个子线程,仍在主线程执行任务。 调用start()会新建一个子线程并执行run()的内容。调用start()会有两个线程,一个是当前正在调用start()的主线程;另一个是JVM创建的子线程,用来执行run()的内容。 实践 实践出真知~~首先写下测试代码: public class ThreadTest { static void printThreadName(){ System.out.println("printThreadName: "+Thread.currentThread().getName()); } public static void main(String[] args) { // 也可用lambda表达式替换,更简洁:new Thread(() -> printThreadName()); Thread thread = new Thread(){ @Override public void run() { printThreadName(); } }; System.out.println("main thread name: "+Thread.currentThread().getName()); thread.run();

JVM -- java内存区域

99封情书 提交于 2019-12-04 06:02:30
一、运行时数据区域   java虚拟机在执行java程序的过程中会把它所管理的内存划分为若干个不同数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。 二、区域介绍    1. 程序计数器     程序计数器(Program Counter Register)是一块较小的内存空间,是当前线程所执行的字节码的行号指示器。(在VM的概念模型里,字节码解释器的工作是。通过改变计数器的值,选取下一条需要执行的字节码指令,分支、循环、跳跃、异常处理、线程恢复等基础功能,这些都学要计数器来完成)。     JVM的多线程是通过 线程轮流切换并分配处理器执行时间 的方式来实现的,在任何一个确定的时刻,一个处理器只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有 独立的程序计数器 ,且各线程的计数器 互不影响,独立储存 。所以像这种内存区域为“ 线程私用 ”的内存。     如果线程正在执行的是一个Java方法, 这个计数器 记录 的是正在执行的 虚拟机字节码指令的地址 ; 如果正在执 行的是Native方法 , 这个计数器值则 为空( Undefined). 此内存区域是 唯一 一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域.。    2.

读书笔记之三:垃圾回收算法前奏 -- 判断对象是否存活

烂漫一生 提交于 2019-12-04 05:47:33
一、引用的定义 JDK 1.2 之前,Java 中引用的定义很传统:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。这种定义很纯粹,但太过狭隘,一个对象在这种定义下只有被引用和没有被引用两种状态,对于一些“食之无味,弃之可惜”的对象显得无能为力。 为描述这样一类对象:当内存空间足够时,则能保留在内存中;如果内存空间在进行垃圾回收后还是非常紧张,则可以抛弃这些对象。很多系统的缓存功能都符合这样的应用场景。 JDK 1.2 之后,Java 对引用的概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,引用强度依次逐渐减弱。 1.1 强引用 强引用就是指在程序代码中普遍存在的,类似“Object obj = new Object()” 这类的引用, 垃圾收集器永远不会回收该引用类型的对象。 1.2 软引用 软引用用来描述一些还有用但是非必需的对象。这类引用对象, 在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。 如果这次回收还没有足够的内存,才会抛出内存溢出异常。在 JDK 1.2 之后,提供了 SoftReference 类来实现软引用。 1.3

java 垃圾回收机制

空扰寡人 提交于 2019-12-04 04:45:23
垃圾收集 GC (Garbage Collection)是Java语言的核心技术之一, 在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了 JVM 来处理。 一. jvm的内存结构 垃圾回收都是基于内存去回收的,因此,先要对内存结构有一个大概的了解 Java内存运行时区域大概分了三部分 其中PC寄存器、java虚拟机栈、本地方法栈3个区域是所有线程独有的一块区域,随线程而生,随线程而灭。栈中的栈帧随着方法的进入和退出而有条不紊地执行着入栈和出栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需要过多考虑回收的问题,因为方法结束或者线程结束,内存自然就跟随着回收了。 而Java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,只有在程序处于运行期间时才能知道会创建哪些对象,这部分内存的分配和回收是动态的,垃圾收集关注的是这部分的内存。 二 . 内存分配 在解垃圾回收之前,得先了解JVM是怎么分配内存的,然后识别哪些内存 是垃 圾需要回收,最后才是用什么方式回收。 Java的内存分配原理与C/C++不同,C/C++每次申请内存时都要malloc进行系统调用,而系统调用发生在内核空间

读书笔记之一:程序计数器、虚拟机栈和本地方法栈

痞子三分冷 提交于 2019-12-04 04:36:49
一、程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号计数器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。 由于 Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。 因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,称这类内存区域为“线程私有”的内存。 如果线程正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是 Native 方法,这个计数器值则为空(Undefined)。 此内存区域是唯一一个在 Java 虚拟机器规范中没有规定任何 OutOfMemoryError 情况的区域。 二、Java 虚拟机栈 与程序计数器一样,Java 虚拟机栈(Java Virtual Machine Stacks)也是 线程私有 的,它的 生命周期与线程相同 。虚拟机描述的是 Java

Java day20 高级编程【第一章】Java多线程编程

橙三吉。 提交于 2019-12-04 04:24:34
【第一章】Java多线程编程 一.进程与线程 多个时间段会有多个程序依次执行,但是同一时间点只有一个进程执行 线程是在进程基础之上划分的更小的程序单元 ,线程是在进程基础上创建并且使用的,所以线程依赖于进程的支持,但是来讲,线程的启动速度要比进程快许多,所以使用多线程进行并发处理的时候,执行的性能要高于进程。 二.Thread类实现多线程 如果想要在JAVA中实现多进程,就必须有一个专门的线程类进行线程执行任务的定义,而这个主体类的定义是有要求的,必须实现特定的接口或者继承特定的父类才可以完成。 1.继承Thread类实现多线程 java里面提供有一个java.lang.Thread的一个程序类,一个类只要继承了此类,并且覆写了Thread类中提供的run()方法,就表示这个类是线程的主体类,而这个方法就是线程的主方法。 范例:多线程主体类: class Mythread extends Thread{ //线程主体类 private String title; public Mythread(String title) { this.title = title; } @Override public void run() { //线程主体方法 for (int x = 0; x<10;x++) { System.out.println(this.title + "运行 x ="