环境
- 7台虚拟机,三master三node,一台作为Docker私库
- VIP
- 192.168.11.222
- master
- 192.168.11.31
- 192.168.11.32
- 192.168.11.33
- node
- 192.168.11.34
- 192.168.11.35
- 192.168.11.36
- Harbor registry
- 192.168.11.200
深度沉迷学习
因为最近在做大数据分析大作业,要求将算法封装进 Docker ,因此临时学了一下 Docker 方面的知识,在这里简单记录一下。
Docker 安装比较简单,可以参考网上教程
使用 Docker 前需要首先理解 Docker 的架构,因为以前自己只使用过 Vmware/VirtualBox 之类虚拟机,所以之前对 Docker 的理解也跟对 Vmware/VirtualBox 认识差不多,但学习之后发现他们还是有很大区别的, Docker 中融汇了面向对象的思想。网上有两张图对初学者很友好,让人很容易理解 Docker 架构思想:
Docker | 面向对象 |
---|---|
容器 | 对象 |
镜像 | 类 |
理解了上面几句话,大概就能跟我一样简单使用了,Docker hub 仓库其实就相当于打包了很多常用的 Docker 镜像,我们可以直接 pull 下来,启动成容器来在本地跑,省去了很多搭环境浪费的时间。
本人虽然最近偏向Java语言,但平常有时也会遇到需要临时调试些C/C++代码,虽然电脑装了VS又感觉有点大材小用,而我平常一直是在用VSCode写markdown等,实际上VSCode和Sublime、Notepad++等都有很多插件可以装,装完就可以当作“短小精悍”的IDE啦,下面就记录下前天在Win10下用VSCode搭建C/C++环境的过程。
在 VSCode 左侧第5个插件商店下面搜索C/C++
,出现第一个插件应该就是微软官方插件,长这样:
这部分主要介绍Java并发包中与锁相关的API和组件的使用和实现。
Lock接口之前Java是靠synchronized关键字实现锁功能的,而Java SE 5后并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,它提供了与synchronized关键字类似的同步功能,只是在使用时需要显式地获取和释放锁。虽没有了隐式释放锁的便利性,但有了如下优点:
Lock使用方式:
|
|
现代操作系统调度的最小单元是线程,也叫轻量级进程(LightWeight Process),在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。
|
|
在命令式编程中,线程之间通信机制有两种:共享内存和消息传递。
Java 并发采用共享内存模型,Java 线程间通信总是隐式进行,整个通信过程对程序员完全透明。
Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和CPU的指令。
volatile 是轻量级 synchronized,它在多处理器开发中保证了共享变量的“可见性”。
可见性:当一个线程修改一个共享变量时,另外一个线程能读到这个修改后的值。
若 volatile 变量修饰符使用恰当,它比 synchronized 使用和执行成本更低,因为它不会引起线程上下文切换和调度。
Java 语言规范对 volatile 的定义:Java 编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应确保通过排它锁单独获得这个变量。Java 语言提供了 volatile,在某些情况下比锁更加厉害。若一个字段被声明为 volatile,Java 线程内存模型确保所有线程看到这个变量的值是一致的。
单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。
上下文切换:任务从保存到再加载的过程就是一次上下文切换。
不一定,因为线程有创建和上下文切换开销。
方法:
new、getstatic、putstatic 或 invokestatic
这 4 条字节码指令时,如果类没有进行初始化,则需要先触发其初始化。生成这 4 条指令的最常见的 Java 代码场景是:使用 new 关键字实例化对象的时候、读取或设置一个类的静态字段(被 final 修饰、已在编译器把结果放入常量池的静态字段除外)的时候,<clinit>()
方法的过程类初始化阶段是类加载过程的最后一步,前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码(或者说是字节码)。
在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器方法的过程。
【深入理解JVM】:类加载机制
Java虚拟机类加载机制
类加载机制
【Java面试题】之类加载:从面试题分析Java类加载机制
[深入理解JVM 六]—-虚拟机字节码执行系统
Java方法执行
【深入Java虚拟机】之五:多态性实现机制——静态分派与动态分派
|
|
线程安全性问题三要素:
- 多线程
- 要有共享资源
- 对共享资源进行非原子性操作
|
|
|
|
|
|
每个栈帧不完全独立,实际上局部变量表的部分数据重叠
栈帧、局部变量表、操作数栈
动态语言支持
方法调用并不等同于方法的执行,方法调用阶段的唯一任务就是确定被调用方法的版本
类加载过程中的解析作用:将 class 文件中的符号引用解析成直接引用
静态方法、构造器方法、私有方法和被 final 修饰的方法不能被重写、重载,编译完就能确定版本
静态分派调用主要针对方法的重载(编译期确定?):
方法调用时会选一个最先匹配的执行:
|
|
动态分派调用针对方法的重写: