avatar

正进一步

只有喜欢,才会全情投入,才会成功!!!

不关注架构设计细节的程序员不是一个好架构师

  • Home
  • Tags
  • Categories
  • Archives
  • 2018寄语
微服务发布模型
  • 滚动发布 部分发布
  • 蓝绿发布 全部发布,但是新老版本共存
  • 金丝雀发布/灰度发布

注释

矿井中的金丝雀 17世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气中哪怕有极其微量的瓦斯,金丝雀也会停止歌唱;而当瓦斯含量超过一定限度时,虽然鲁钝的人类毫无察觉,金丝雀却早已毒发身亡。当时在采矿设备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为“瓦斯检测指标”,以便在危险状况下紧急撤离。

Java等号右边计算过程_i++例子

查缺补漏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

public static void main(String[] args) {
int i = 0;
int m = 0;
for (int j = 0; j < 10; j++) {
{
i=i++;
}
{ //相当于下面的代码
int temp= m;
m++;
m= temp;
}
}
System.out.println("i的最后结果"+i);
System.out.println("m的最后结果"+m);
}

结果:

1
2
i的最后结果0
m的最后结果0

Volatile作用及面试内容

引用自: https://mp.weixin.qq.com/s/bvqVBnYPdFvpQqdB_4kdUQ

volatile 能使得一个非原子操作变成原子操作吗?

一个典型的例子是在类中有一个long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,你最好是将其设置为 volatile。为什么?因为 Java 中读取long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个 volatile 型的 long 或double 变量的读写是原子。

volatile 类型变量提供什么保证?

volatile 变量提供顺序和可见性保证,例如,JVM或者 JIT为了获得更好的性能会对语句重排序,但是 volatile 类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。 volatile 提供 happens-before 的保证,确保一个线程的修改能对其他线程是可见的。某些情况下,volatile 还能提供原子性,如读 64 位数据类型,像 long 和 double 都不是原子的,但 volatile 类型的 double 和 long 就是原子的。

volatile 修饰符的有过什么实践?

一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和 long 都是64位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但Java 中 volatile 型的 long 或 double 变量的读写是原子的。volatile 修复符的另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(writebarrier),读一个volatile 变量之前,会插入一个读屏障(read barrier)。意思就是说,在你写一个volatile 域时,能保证任何线程都能看到你写的值,同时,在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。

21用函数对象表示策略

实现函数对象的几种方式:

  • C语言的函数指针
  • lambda表达式
  • 函数式接口

函数对象主要用于策略模式.只用一次的话,使用匿名内部类;多次使用的话,可以导出成一个成员域(static final修饰)

实例:
java.util.Comparator

21用函数对象表示策略

实现函数对象的几种方式:

  • C语言的函数指针
  • lambda表达式
  • 函数式接口

函数对象主要用于策略模式.只用一次的话,使用匿名内部类;多次使用的话,可以导出成一个成员域(static final修饰)

实例:
java.util.Comparator

19接口只用于定义类型

当类实现接口时 ,接口就充当可以引用这个类的实例的类型(type)。因此,类实现了接口,就表明客户端可以对这个类的实例实施某些动作。为了任何其他目的而定义接口是不恰当的。

有一种接口被称为常量接口(constant interface),它不满足上述条件。这种接口没有方法,只有静态final域。常量接口模式是对接口的不良使用。这样做不仅会暴露该类的实现细节到导出API中,还会产生一个更糟糕的情况。就是在将来的发行版中,如果类不再需要使用这些常量,它依然必须实现这个接口,以确保二进制兼容性。如果非final类实现了常量接口,它的所有子类的命名空间也会被接口中的常量所“污染”。

反例

Java平台类库中有几个常量接口,例如java.io.ObjectStreamConstants。这些接口应该被认为是反面的典型,不值得效仿。

方案。

1.如果常量与某个现有类或接口紧密相关,就应该把这些常量添加到这个类或接口中。

2.如果这些常量可以被看作枚举类型的成员,就应该用枚举类型(enum type)。

3.用不可实例化的工具类( utility class)。使用静态导入(import static)避免常量修饰.

MySQL Binlog解析

引用自:
https://yq.aliyun.com/articles/238364?spm=5176.10695662.1996646101.searchclickresult.4e582ae9RunAqR

MySQL Server 有四种类型的日志——Error Log、General Query Log、Binary Log 和 Slow Query Log。

第一个是错误日志,记录 mysqld 的一些错误。第二个是一般查询日志,记录 mysqld 正在做的事情,比如客户端的连接和断开、来自客户端每条 Sql Statement 记录信息;如果你想准确知道客户端到底传了什么瞎 [哔哔] 玩意儿给服务端,这个日志就非常管用了,不过它非常影响性能。第四个是慢查询日志,记录一些查询比较慢的 SQL 语句——这种日志非常常用,主要是给开发者调优用的。

剩下的第三种就是 Binlog 了,包含了一些事件,这些事件描述了数据库的改动,如建表、数据改动等,也包括一些潜在改动,比如 DELETE FROM ran WHERE bing = luan,然而一条数据都没被删掉的这种情况。除非使用 Row-based logging,否则会包含所有改动数据的 SQL Statement。

那么 Binlog 就有了两个重要的用途——复制和恢复。比如主从表的复制,和备份恢复什么的。

显然,我们执行SELECT等不设计数据变更的语句是不会记录Binlog的,而涉及到数据更新则会记录。要注意的是,对支持事务的引擎如InnoDB而言,必须要提交了事务才会记录Binlog。Binlog是在事务最终commit前写入的,binlog什么时候刷新到磁盘跟参数sync_binlog相关。如果设置为0,则表示MySQL不控制binlog的刷新,由文件系统去控制它缓存的刷新,而如果设置为不为0的值则表示每sync_binlog次事务,MySQL调用文件系统的刷新操作刷新binlog到磁盘中。设为1是最安全的,在系统故障时最多丢失一个事务的更新,但是会对性能有所影响,一般情况下会设置为100或者0,牺牲一定的一致性来获取更好的性能。

慎用可变参数
  • 至少传递一个
1
2
3
4
5
private static <E> void varargs(Object obj,E...varargs){
for(E e : varargs){
System.out.println(e);
}
}
  • 泛型编程只能接受引用类型

  • 打印数组tostring,会导致没有意义的字符结果

  • 可变参数每次调用都会导致有一次数组分配和初始化

  • EnumSet静态工厂最大限度地减少创建枚举集合的成本

1
2
3
4
5
6
7
public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
EnumSet<E> result = noneOf(first.getDeclaringClass());
result.add(first);
for (E e : rest)
result.add(e);
return result;
}
  • Arrays.toString(int[] args)可以打印数组,而不是可变参数
江城子-宋朝-苏轼
江城子 宋朝-苏轼-乙卯(1075)年正月二十日夜记梦
十年生死两茫茫,不思量,自难忘。千里孤坟,无处话凄凉。纵使相逢应不识,尘满面,鬓如霜
夜来幽梦忽还乡,小轩窗,正梳妆。相顾无言,惟有泪千行。料得年年肠断处,明月夜,短松冈
优先使用Lamdba,而不是匿名内部类
  • Lambda没有文档和名字,如果不能方法体太长或者不能自解释的话,那么就不要放到lamdba中。

  • Lambda不能使用this访问自身。this在Lambda是访问的外部类。如果要在方法体中访问自身的话,那么就不能使用Lambda

  • 不要在创建函数对象的时候使用匿名内部类,除非创建的对象不是函数式接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public enum Operation {
PLUS ("+", (x, y) -> x + y),
MINUS ("-", (x, y) -> x - y),
TIMES ("*", (x, y) -> x * y),
DIVIDE("/", (x, y) -> x / y);
private final String symbol;
private final DoubleBinaryOperator op;
Operation(String symbol, DoubleBinaryOperator op) {
this.symbol = symbol;
this.op = op;
}
@Override public String toString() { return symbol; }
public double apply(double x, double y) {
return op.applyAsDouble(x, y);
}
}