线程

初始JVM

a 夏天 提交于 2020-03-01 20:04:05
这几天面试,问了一些JVM的知识感觉答的不是很好,在此写JVM系列的文章(再次讨论的是java8的相关知识点),回顾一下相关知识,希望能够帮到看我文章的朋友,现在马上开始。 相关概念: 1.什么是jvm?(java virtual machine) Java虚拟机是抽象的计算机。像真正的计算机一样,它具有指令集并在运行时操作各种内存区域。 2.什么是运行时数据区? Java虚拟机定义了在程序执行期间使用的各种运行时数据区域。其中一些数据区域是在Java虚拟机启动时创建的,仅在Java虚拟机退出时才被销毁。其他数据区域是每个线程的。创建线程时创建每个线程的数据区域,并在线程退出时销毁每个数据区域。 The Java Virtual Machine defines various run-time data areas that areused during execution of a program. Some of these data areas are created on Java Virtual Machine start-up and are destroyed only whenthe Java Virtual Machine exits. Other data areas are per thread.Per-thread data areas are

Flask框架(二)

早过忘川 提交于 2020-03-01 19:19:01
目录 一、请求扩展 1.1befor_request 1.2after_request 1.3before_first_request 1.4teardown_request 1.5errhandler(错误码) 1.6template_global() 1.7template_filter() 二、flask中间件 三、flask蓝图 3.1蓝图的介绍与使用 3.2蓝图的高级使用(重点内容) 3.3使用蓝图之中小型系统 3.4使用蓝图之使用大型系统 四、flask之协程和线程 4.1threading.local 4.2通过字典自定义threading.local 4.3通过setattr和getattr实现自定义threthreading.local 4.4每个对象有自己的存储空间(字典) 4.5如何设计flask的请求并发? 五、偏函数 一、请求扩展 1.1befor_request 1.app.befor_request装饰过得函数在真正的响应函数之前执行,可以有多个,当有多个的时候,执行顺序是谁在前面谁先执行。 2.只要一个befor_request有返回值,那后面所有的befor_request都不会执行,真正的响应函数也不会执行。 3.被befor_request装饰的函数可以没有return。 from flask import Flask,render

线程理论基础

风流意气都作罢 提交于 2020-03-01 18:05:04
一、进程与线程 进程 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据 加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的。 当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。 进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程(例如记事本、画图、浏览器等),也有的程序只能启动一个实例进程(例如网易云音乐、360 安全卫士等) 线程 一个进程之内可以分为一到多个线程。 一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给 CPU 执行。 Java 中,线程作为最小调度单位,进程作为资源分配的最小单位。 在 windows 中进程是不活动的,只是作为线程的容器 二者对比 进程基本上相互独立的,而线程存在于进程内,是进程的一个子集 进程拥有共享的资源,如内存空间等,供其内部的线程共享 进程间通信较为复杂 同一台计算机的进程通信称为 IPC(Inter-process communication) 不同计算机之间的进程通信,需要通过网络,并遵守共同的协议,例如 HTTP 线程通信相对简单,因为它们共享进程内的内存,一个例子是多个线程可以访问同一个共享变量 线程更轻量,线程上下文切换成本一般上要比进程上下文切换低 二、并行与并发 并发

异步与非阻塞

*爱你&永不变心* 提交于 2020-03-01 17:10:45
异步和非阻塞调用之间有什么区别? 阻塞和同步调用之间(请举例)? #1楼 将此问题放在Java 7中的NIO和NIO.2的上下文中,异步IO比非阻塞更先进一步。 使用java NIO非阻塞调用,可以通过调用 AbstractSelectableChannel.configureBlocking(false) 来设置所有通道(SocketChannel,ServerSocketChannel,FileChannel等 AbstractSelectableChannel.configureBlocking(false) 。 但是,在这些IO调用返回之后,您可能仍需要控制检查,例如是否以及何时再次读/写等。 例如, while (!isDataEnough()) { socketchannel.read(inputBuffer); // do something else and then read again } 使用java 7中的异步api,可以以更通用的方式创建这些控件。 两种方法之一是使用 CompletionHandler 。 请注意,两个 read 调用都是非阻塞的。 asyncsocket.read(inputBuffer, 60, TimeUnit.SECONDS /* 60 secs for timeout */, new CompletionHandler

JVM层GC调优(上)

混江龙づ霸主 提交于 2020-03-01 16:47:10
JVM内存结构简介(jdk1.8) JVM层的GC调优是生产环境上必不可少的一个环节,因为我们需要确定这个进程可以占用多少内存,以及设定一些参数的阀值。以此来优化项目的性能和提高可用性,而且这也是在面试中经常会被问到的问题。 想要进行GC调优,我们首先需要简单了解下JVM的内存结构,Java虚拟机的规范文档如下: https://docs.oracle.com/javase/specs/jvms/se8/html/index.html 在介绍JVM内存结构之前,我们需要先知道 运行时数据区 这样的一个东西,它与JVM的内存结构有着一定的关联。不过它属于是一个规范,所以与JVM内存结构是有着物理上的区别的。运行时数据区如下: 1.程序计数器(Program Count Register,简称PC Register): JVM支持多线程同时执行,每一个线程都有自己的PC Register。当每一个新线程被创建时,它都将得到它自己的PC Register。线程正在执行的方法叫做当前方法。如果执行的是Java方法,那么PC Register里存放的就是当前正在执行的指令的地址,如果是native方法(C/C++编写的方法),则是为空。此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。 2.虚拟机栈(JVM Stacks): Java虚拟机栈

JVM内存结构

天大地大妈咪最大 提交于 2020-03-01 16:41:22
1.jdk、jre、jvm jdk包含jre,jre包含jvm. jdk是一个合集,包括一些编译工具 jre是Java运行环境,包含一些插件 jvm是最基础的,做翻译的,将class翻译成操作系统是的指令(0101) 2.运行时数据区 线程私有 :程序计数器、虚拟机栈、本地方法栈 线程共享 :堆、方法区 程序计数器 (唯一不会OOM的区域):记录指向当前线程正在执行的字节码指令的地址(行号) Java是多线程的,意味着线程切换,确保多线程情况下的程序正常执行。 栈 (stack):一种数据结构 为什么jvm要使用栈?答:更好的兼容方法调用方法的特点。 虚拟机栈 (大小设置 -Xss 1M,虚拟机栈就是在栈数据结构上的一个种拓展):存储当前线程运行方法所需的数据,指令、返回地址 栈帧 :多个方法,每个方法就是一个栈帧 方法转换为字节码,在虚拟机中运行过程 栈默认大小为1M,StackOverFlowError(栈溢出)的出现是因为方法死递归调用本方法,导致内存超出1M。 OOM栈内存溢出,很多线程在跑,10万个线程栈空间就是10万*1M,导致内存不足。 本地方法栈 :是保存的native方法信息,jvm调用后,jvm不为其在虚拟机中创建栈帧,jvm只是简单动态并直接调用native方法。 方法区 (永久代jdk1.7及以前,元空间jdk1.8):存放类信息、常量(final)

线程间的通信

扶醉桌前 提交于 2020-03-01 16:35:53
一,概述。    1.什么叫做线程间通信: 在1个进程中,线程往往不是孤立存在的,线程之间需要一些协调通信,来共同完成一件任务。也就是通过一定的方法来实现线程间的“交流”。   2.线程间通信的体现:     - 1个线程传递数据给另1个线程     - 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 二,线程通信的方法。    Object类中相关的方法有两个notify方法和三个wait方法:notify() / notifyAll() / wait()   因为wait和notify方法定义在Object类中,因此会被所有的类所继承。这些方法都是 final 的,即它们都是不能被重写的,不能通过子类覆写去改变它们的行为。    1.wait()方法。     语法:锁对象.wait()   特点:wait()方法的调用使得当前线程必须要等待,直到另外一个线程调用notify()或者notifyAll()方法。      wait()方法的调用必须在同步的前提下。(因为该方法是要用锁对象调用,而只有在同步的情况下才有锁)      wait()方法的调用会导致锁的释放。   线程调用wait()方法,释放它对锁的拥有权,然后等待另外的线程来通知它(通知的方式是notify()或者notifyAll()方法),这样它才能重新获得锁的拥有权和恢复执行。要确保调用wait(

JVM中的对象

柔情痞子 提交于 2020-03-01 16:31:47
划分对象 两种方式: 指针碰撞:java内存空间规整的请款下使用 空闲列表:java内存空间不规整的请款下使用 并发安全问题:频繁创建对象就会存在线程不安全问题。解决方案有两种: 1.对分配内存空间的操作进行同步处理,CAS加失败重试机制保证保证更新操作原子性。 2.分配缓冲:给每个线程分配独立空间(Java堆中申请一小块私有内存),也就是本地线程分配缓冲(Tread Local Allocation Buffer,TLAB),开启 -XX:+UseTLAB,在自己Buffer分配,空间不够重新在Eden区申请一块继续使用。 TLAB可以让每个应用线程拥有专属的分配指针来分配空间(Eden区,默认Eden的1%),减小同步开销。 TLAB只是让每个线程有私有的分配指针,但底下存对象的内存空间还是给所有线程访问的,只是其他线程无法在这个区域分配而已。当一个TLAB用满(分配指针top撞上分配极限end了),重新申请一个TLAB. 对象内存布局 在HotSpot虚拟机中,对象的内存布局分为:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding) 对象头分配两部分,一是自身运行时数据(哈希吗HashCode)、GC分带年龄、锁状态标志、线程持有锁、偏向线程ID、偏向时间戳等。 另一种类型指针,即只想它的类元素指针,虚拟机通过这个指针来确定是哪个类的实例

java内存区域----运行时数据区

别等时光非礼了梦想. 提交于 2020-03-01 16:14:59
Java虚拟机的内存区域也叫做java运行时数据区,共分为五个部分:程序计数器,方法区,本地方法栈,虚拟机栈和堆。方法区和堆是线程之间所共有的,程序计数器,本地方法栈,虚拟机栈是线程私有的。其中虚拟机栈和堆是程序员日常谈论最多也是最关注的一部分。 程序计数器:程序计数器就是指向当前线程要执行的字节码。字节码解释器通过改变这个值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等都需要依赖计数器来完成。每一个线程都拥有一个计数器,互不影响。(注:如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟字节码指令的地址,如果正在执行的是本地方法,这个计数器值为空,此内存区域是唯一一个在《java虚拟机规范》中没有规定任何OutOfMemoryError情况的区域)。通俗点说程序计数器就是用来指示我该执行哪条字节码指令了。 方法区:各个线程共享的内存区域,用于存储被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存,运行时常量池等数据。(注:《java虚拟机规范》中把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫“非堆”,目的是与java堆区分开来)。方法区不需要使用连续的内存,可以选择固定大小或者对外扩展,甚至可以选择不实现垃圾收集。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。运行时常量池是方法区的一部分

synchronized的可重入怎么实现。

拟墨画扇 提交于 2020-03-01 16:09:09
每个锁关联一个线程持有者和一个计数器。当计数器为0时表示该锁没有被任何线程持有,那么任何线程都都可能获得该锁而调用相应方法。当一个线程请求成功后,JVM会记下持有锁的线程,并将计数器计为1。此时其他线程请求该锁,则必须等待。而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增。当线程退出一个synchronized方法/块时,计数器会递减,如果计数器为0则释放该锁。 来源: oschina 链接: https://my.oschina.net/u/4167465/blog/3182838