使用 dockerfile-maven-plugin 插件构建并推送 Docker 镜像

这篇笔记的目标是使用本地 IDEA 编译 SpringBoot 工程为 jar 包,并且使用安装好 Docker 的远程 Linux 主机构建 Docker 镜像,Push 到阿里云的镜像托管服务。

首先需要一台安装好 Docker 的 Linux 主机或虚拟机,并且开放远程控制(见 -> 开启 Docker 的远程控制

添加环境变量

IDEA 设置里添加 Maven 环境变量,告知 Docker Host 地址,具体操作如下:

  1. 找到 Preference -> Build, Execution, Deployment -> Build Tools -> Maven -> Runner
  2. 在 Environment variables 中填写 DOCKER_HOST=tcp://xxx.xxx.xxx.xxx:2375
阅读更多

一些容易忘掉的知识点 - Java

1 Java 基础

1.1 快速失败(fail-fast)和安全失败(fail-safe)机制

快速失败(fail-fast)是 Java 集合的一种错误检测机制。

使用迭代器对集合进行遍历的时候,在多线程下操作非安全失败(fail-safe)的集合类可能就会触发 fail-fast 机制,导致抛出 ConcurrentModificationException 异常。

在单线程下,如果在遍历过程中对集合对象的内容进行了修改的话也会触发 fail-fast 机制。

例如:多线程下,如果线程 1 正在对集合进行遍历,此时线程 2 对集合进行修改(增加、删除、修改),或者线程 1 在遍历过程中对集合进行修改,都会导致线程 1 抛出 ConcurrentModificationException 异常。

原理

迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变 modCount 的值。

每当迭代器使用 hashNext ()/next () 遍历下一个元素之前,都会检测 modCount 变量是否为 expectedmodCount 值,是的话就返回遍历;否则抛出异常,终止遍历。

采用安全失败(fail-safe机制的集合容器(JUC 包下的容器),在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历,可以在多线程下并发使用,并发修改。所以,在遍历过程中对原集合所作的修改并不能被迭代器检测到,故不会抛 ConcurrentModificationException 异常。

1.2 HashMap 与 ConcurrentHashMap 对 null 值的处理问题

结论:HashMap 的 key 和 value 都可以为 null,ConcurrentHashMap 的均不可以为 null

HashTable 也是不允许 key 和 value 为空的,原因和 ConcurrentHashMap 一致

上源码!

HashMap,当 key 为 null 的时候,hash 值为 0,后续的 put 方法中也没有判断 value 是否为 null 的代码。

1
2
3
4
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

ConcurrentHashMap,key 或 value 为 null 直接抛出空指针异常!

1
2
3
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
......

这么做的原因:

会有一个问题,当通过 get(k) 获取对应的 value 时,如果获取到的是 null,无法判断它是 put(k,v) 的时候 value 为 null,还是这个 key 从来没有做过映射。

HashMap 多用于非并发场景中,可以通过 contains(key) 来做这个判断。而在多用于并发场景中的 ConcurrentHashMap 中调用 m.contains(key) 判断然后再 m.get(key) 时,m 可能已经被其他线程修改而不同了。为了避免这种二义性,ConcurrentHashMap 在设计之初就直接令 key 和 value 都不为 null。

阅读更多

MapReduce 的学习

HDFS 和 MapReduce 是 Hadoop 的两个重要核心,其中 MapReduce 是 Hadoop 的分布式计算模型。MapReduce 主要分为两步 Map 步和 Reduce 步,引用网上流传很广的一个故事来解释,现在你要统计一个图书馆里面有多少本书,为了完成这个任务,你可以指派小明去统计书架 1,指派小红去统计书架 2,这个指派的过程就是 Map 步,最后,每个人统计完属于自己负责的书架后,再对每个人的结果进行累加统计,这个过程就是 Reduce 步。

本代码运行环境为 ubuntu 18.04,使用 Hadoop 2.9.2 版本
首先按照之前的方法(在 CentOS 7 中安装 Hadoop 与 HBase)搭建并启动 Hadoop

阅读更多