本地线程

Java虚拟机内存区域

喜欢而已 提交于 2019-12-20 07:16:13
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间。根据Java虚拟机规范,包括以下几个运行时数据区。 一、程序计数器 内存空间:较小。 作 用:当前线程所执行的字节码的行号指示器。 特性分析:Java虚拟机的多线程的执行是由线程轮流切换并分配处理器执行时间来完成的。在确定的某个时刻,一个处理器只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的的执行位置,每条线程都需要一个独立的程序计数器,各个线程之间计数互不影响,独立存储。 是线程私有的内存区域。 记录值:如果线程执行的是Java方法,那么记录的是正在执行的虚拟机字节码指令地址;如果线程执行的是Native方法,那么这个值为空。 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError的区域。 二、Java虚拟机栈 是线程私有的,生命周期与线程相同。 作用:描述的是Java方法执行的内存模型:每个方法被执行的时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在栈中的入栈和出栈过程。 虚拟机栈中的局部变量表存放了 编译期可知的各种 基本数据类型(boolean、byte、char、short、int、float、long、double)

Volatile关键字

耗尽温柔 提交于 2019-12-20 04:10:01
1.什么是Volatile ThreadLocal可见性也就是说一旦某个线程修改了该被volatile修饰的变量,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,可以立即获取修改之后的值。 ThreadLocal在Java中为了加快程序的运行效率,对一些变量的操作通常是在该线程的寄存器或是CPU缓存上进行的,之后才会同步到主存中,而加了volatile修饰符的变量则是直接读写主存。 ThreadLocalVolatile 保证了线程间共享变量的及时可见性,但不能保证原子性 2.JMM(Java内存模型) 要搞懂Volatile首先要了解一下Java内存模型 共享内存模型指的就是Java内存模型(简称JMM), JMM决定一个线程对共享变量的写入时,能对另一个线程可见 。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系: 线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本 。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。 从上图来看,线程A与线程B之间如要通信的话,必须要经历下面2个步骤: (1) 首先,线程A把本地内存A中更新过的共享变量刷新到主内存中去。 (2) 然后

java内存结构

折月煮酒 提交于 2019-12-19 16:45:19
Java 的内存结构 JVM 的内存结构主要有三大块:堆、方法区和栈。堆内存是 JVM 中最大的一块,由 年轻代和老年代 组成,而年轻代内存又被分为三部分, Eden 空间、 FromSurvivor 空间和 ToSurvivor 空间,默认情况下年轻代是按照 8:1:1 的比例来分配。 方法区存储类信息、常量、静态变量等数据,是线程共享的区域,为与 Java 堆区分,方法区还有一个别名 Non-Heap (非堆);栈又分为 Java 虚拟机栈和本地方法栈主要用于方法的执行。 JVM 和系统调用之间的关系 方法区和堆是所有线程共享的内存区域;而java 虚拟机栈、本地方法栈和程序员计数器是线程私有的内存区域。 1. Java 堆( Heap ) 对于大多数应用来说, Java 堆( Java Heap )是 Java 虚拟机所管理的内存中最大的一块 , Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 Java 堆是垃圾收集器管理的主要区域,因此很多时候也被成为“ GC 堆”。如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以 Java 堆中还可以细分为: 新生代 和 老年代 ,再细致一点的有 Eden 空间、 From Survivor 空间、 ToSurvivor

java线程启动原理分析

烂漫一生 提交于 2019-12-19 12:08:33
一、前言 不知道哪位古人说:人生三大境界。第一境界是:看山是山看水是水;第二境界是看山不是山看水不是水;第三境界:看山还是山看水还是水。 其实我想对于任何一门技术的学习都是这样。 形而上下者为之器,形而上者为之道。一直很喜欢自己大一的高数老师,老师是老教授了,他讲数学,会引申到建筑学,计算机科学,以及哲学再到生活中的常识。也能从其他学科、日常生活中,提取出数学的概念。我想,这就是形而上者了。 不胜望之 不多言,这里我们来深入java底层,看下java表皮之下的筋肉以及内脏。 二、从一段代码展开 package thread; /** * @author xuyuanpeng * @version 1.0 * @date 2019-05-17 17:04 */ public class ThreadMain { public static void main(String[] args) { Thread thread=new Thread(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread t2=new Thread(() -> { try { Thread.sleep(1000); } catch

多线程死锁

主宰稳场 提交于 2019-12-19 04:54:11
1.什么是死锁? 死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 2.死锁产生的原因 1.因为系统资源不足。 2.进程运行推进的顺序不合适。 3.资源分配不当。 产生死锁的条件有四个: 1.互斥条件:所谓互斥就是进程在某一时间内独占资源。 2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。 4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。 3.图解死锁产生的过程 1)有两个人——线程A、线程B。有两个房间——房间A、房间B。每个房间上有且仅有一把锁,此处可以把锁理解为进入房间的令牌 2)线程A拿到了a锁并且成功进入了A房间 3)线程B拿到了b锁并且成功进入了B房间 4)线程A拿着a锁想要进入B房间,与此同时线程B拿着b锁想要进入A房间 那么问题来了,线程A想进B房间需要拿到b锁,而b锁在线程B手中.同样,线程B想进A房间需要拿到a锁,而a锁在线程A手中 这样如果在外界没有干预的情况下 A会一直试图进入B房间却拿不到b锁,B也会一直试图进入A房间拿不到a锁 就这样一直耗下去 于是就产生了死锁现象 4.代码模拟上图中死锁现象 package com . lzh ; public class DeadLock

Java线程池实现

微笑、不失礼 提交于 2019-12-19 01:23:20
电脑的CPU资源是有限的,任务的处理速度与线程数量之间并不是正相关。当线程数量过多,CPU要频繁的在不同线程切换,反而会引起处理性能的下降。线程池中最大的线程数,是考虑多种因素来事先设定的,比如硬件的条件,业务的类型等等。 当我们向一个固定大小的的线程池中请求一个线程时,当线程池中没有空闲资源了,这个时候线程池如何处理这个请求?是拒绝请求还是排队请求?各种策略又是如何实现的呢? 实际上,这些问题的处理并不复杂,底层的数据结构,就是队列(queue)。 一、Java线程池介绍 1,线程池的作用 限制系统中执行线程的数量。 减少了创建和销毁线程的次数,重复利用线程。 2,主要的类 Executor:执行线程的接口 ExecutorSerivce: 线程池接口 ThreadPoolExecutor :线程池类 Executors:常用线程池工厂 3,常用的线程池 配置线程池是比较复杂的过程,所有可以使用现有的线程池工厂生成常用的线程池: newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。为了合理利用资源,我们通常把定长池的长度设置为当前PC机获取cpu核心数:Runtime.getRuntime().availableProcessors():获取当前CPU核心数; newCachedThreadPool创建一个可缓存线程池

Java的内存结构

耗尽温柔 提交于 2019-12-18 16:53:39
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> Java 的运行时数据区域分为五大数据区域。这些区域各有各的用途,创建及销毁时间。如下图所示,其中方法区和堆是所有线程共享的,栈,本地方法栈和程序虚拟机则为线程私有的。 根据 Java 虚拟机规范, Java 虚拟机管理的内存分为 方法区、堆、虚拟机栈、本地方法栈、程序计数器栈 五大区域。 程序计数器(Program Counter Register) 程序计数器是一块很小的内存空间,它是线程私有的,可以认作为当前线程的行号指示器。 在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。由于 Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,对于一个处理器(如果是多核 CPU 那就是一核)来说,在一个确定的时刻只会执行一条线程中的指令,而一条线程中有多个指令,为了线程切换可以恢复到正确执行位置,每个线程都需有独立的一个程序计数器,不同线程之间的程序计数器互不影响,独立存储。 如果线程执行的是个 Java 方法,那么计数器记录的是虚拟机字节码指令的地址。如果为 native 底层方法,那么计数器为空( Undefined )。这块内存区域是虚拟机规范中唯一没有

jvm内存模型概述

北城余情 提交于 2019-12-18 12:33:24
一、Jvm 的介绍 1、JVM体系结构 2、JVM运行时数据区 3、JVM内存模型 JVM运行时内存 = 共享内存区 + 线程内存区 3.1、共享内存区 共享内存区 = 持久带(方法区 + 其他)+ 堆(Old Space + Young Space(den + S0 + S1)) 持久代 : JVM用持久带(Permanent Space)实现方法区,主要存放所有已加载的类信息,方法信息,常量池等等。可通过-XX:PermSize和-XX:MaxPermSize来指定持久带初始化值和最大值。 Permanent Space并不等同于方法区,只不过是Hotspot JVM用Permanent Space来实现方法区而已 ,有些虚拟机没有Permanent Space而用其他机制来实现方法区。 堆(heap) : 主要用来存放类的对象实例信息(包括new操作实例化的对象和定义的数组)。 堆分为Old Space(又名,Tenured Generation)和Young Space。Old Space主要存放应用程序中生命周期长的存活对象;Eden(伊甸园)主要存放新生的对象;S0和S1是两个大小相同的内存区域,主要存放每次垃圾回收后Eden存活的对象,作为对象从Eden过渡到Old Space的缓冲地带(S是指英文单词Survivor Space)。堆之所以要划分区间

golang goroutine的调度

℡╲_俬逩灬. 提交于 2019-12-18 09:12:22
golang goroutine的调度 1、什么是协程? 协程是一种用户态的轻量级线程。 2、进程、线程、协程的关系和区别: * 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。 * 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。 * 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。 * 协程和线程的区别是:协程避免了无意义的调度,由此可以提高性能。 * 执行协程只需要极少的栈内存(大概是4~5KB),默认情况下,线程栈的大小为1MB。 goroutine就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。所以它非常廉价,我们可以很轻松的创建上万个goroutine,但它们并不是被操作系统所调度执行。 runtime。GOMAXPROCS(runtime。NumCPU()) // go version>=1.5的时候,GOMAXPROCS的默认值就是go程序启动时可见的操作系统认为的CPU个数。 注意:在go程序中使用的操作系统线程数量包括:正服务于cgo calls的线程,阻塞于操作系统calls的线程,所以go程序中使用的操作系统线程数量可能大于GOMAXPROCS的值。 3、调度 要理解协程的实现,首先需要了解go中的三个非常重要的概念,它们分别是G(goroutine)、M

JVM内存管理(二)

我们两清 提交于 2019-12-18 05:54:02
JVM 内存管理       JVM在执行java程序的过程中,会把内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。 程序计数器    程序计数器:当前线程所执行字节码的行号指示器。    由于 JVM 的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器只会执行一条线程中的指令。为了线程切换后能够恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各线程之间计数器互不影响,独立存储。   程序计数器:线程私有的内存。 Java 虚拟机栈    每个方法在执行的同时,都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。   每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。   局部变量所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。   Java 虚拟机栈,与程序计数器一样,是线程私有的,生命周期同线程相同。 本地方法栈   本地方法栈类似于虚拟机栈,区别在于:虚拟机栈为虚拟机执行 java 方法服务。   本地方法栈则为虚拟机执行 Native 方法服务。 Java 堆