先来引入一个问题
1 | System.err.println(9990000110F<=9990000000F); |
运行结果是: true
然后你的问题就来了,这个是谁大呢?
1 | System.err.println(9990000110F); |
看看结果是什么?1
29.9899996E9
9.9899996E9
其实这两个值在jvm是相等的,float有个规定,当位数超过8位时候自动转为科学计数法,然后就存在失真的情况.记录下,水坑来的.
有温度的程序员
先来引入一个问题
1 | System.err.println(9990000110F<=9990000000F); |
运行结果是: true
然后你的问题就来了,这个是谁大呢?
1 | System.err.println(9990000110F); |
看看结果是什么?1
29.9899996E9
9.9899996E9
其实这两个值在jvm是相等的,float有个规定,当位数超过8位时候自动转为科学计数法,然后就存在失真的情况.记录下,水坑来的.

相信大家对 ZooKeeper 应该不算陌生。但是你真的了解 ZooKeeper 是个什么东西吗?如果别人/面试官让你给他讲讲 ZooKeeper 是个什么东西,你能回答到什么地步呢?
我本人曾经使用过 ZooKeeper 作为 Dubbo 的注册中心,另外在搭建 solr 集群的时候,我使用到了 ZooKeeper 作为 solr 集群的管理工具。前几天,总结项目经验的时候,我突然问自己 ZooKeeper 到底是个什么东西?想了半天,脑海中只是简单的能浮现出几句话:“①Zookeeper 可以被用作注册中心。 ②Zookeeper 是 Hadoop 生态系统的一员;③构建 Zookeeper 集群的时候,使用的服务器最好是奇数台。” 可见,我对于 Zookeeper 的理解仅仅是停留在了表面。
看本文之前如果你没有安装 ZooKeeper 的话,可以参考这篇文章:《使用 SpringBoot+Dubbo 搭建一个简单分布式服务》 的 “开始实战 1 :zookeeper 环境安装搭建” 这部分进行安装(Centos7.4 环境下)。如果你想对 ZooKeeper 有一个整体了解的话,可以参考这篇文章:《可能是把 ZooKeeper 概念讲的最清楚的一篇文章》
ZNode(数据节点)是 ZooKeeper 中数据的最小单元,每个ZNode上都可以保存数据,同时还是可以有子节点(这就像树结构一样,如下图所示)。可以看出,节点路径标识方式和Unix文件
系统路径非常相似,都是由一系列使用斜杠”/“进行分割的路径表示,开发人员可以向这个节点中写人数据,也可以在节点下面创建子节点。这些操作我们后面都会介绍到。
提到 ZooKeeper 数据模型,还有一个不得不得提的东西就是 事务 ID 。事务的ACID(Atomic:原子性;Consistency:一致性;Isolation:隔离性;Durability:持久性)四大特性我在这里就不多说了,相信大家也已经挺腻了。
在Zookeeper中,事务是指能够改变 ZooKeeper 服务器状态的操作,我们也称之为事务操作或更新操作,一般包括数据节点创建与删除、数据节点内容更新和客户端会话创建与失效等操作。对于每一个事务请求,ZooKeeper 都会为其分配一个全局唯一的事务ID,用 ZXID 来表示,通常是一个64位的数字。每一个ZXID对应一次更新操作,从这些 ZXID 中可以间接地识别出Zookeeper处理这些更新操作请求的全局顺序。
每个 ZNode 由2部分组成:
如下所示,我通过 get 命令来获取 根目录下的 dubbo 节点的内容。(get 命令在下面会介绍到)
1 | [zk: 127.0.0.1:2181(CONNECTED) 6] get /dubbo |
这些状态信息其实就是 Stat 对象的格式化输出。Stat 类中包含了一个数据节点的所有状态信息的字段,包括事务ID、版本信息和子节点个数等,如下图所示(图源:《从Paxos到Zookeeper 分布式一致性原理与实践》,下面会介绍通过 stat 命令查看数据节点的状态)。
Stat 类:
关于数据节点的状态信息说明(也就是对Stat 类中的各字段进行说明),可以参考下图(图源:《从Paxos到Zookeeper 分布式一致性原理与实践》)。
进入安装 ZooKeeper文件夹的 bin 目录下执行下面的命令连接 ZooKeeper 服务(Linux环境下)(连接之前首选要确定你的 ZooKeeper 服务已经启动成功)。
1 | ./zkCli.sh -server 127.0.0.1:2181 |
从上图可以看出控制台打印出了很多信息,包括我们的主机名称、JDK 版本、操作系统等等。如果你成功看到这些信息,说明你成功连接到 ZooKeeper 服务。
help 命令查看 zookeeper 常用命令
通过 create 命令在根目录创建了node1节点,与它关联的字符串是”node1”
1 | [zk: 127.0.0.1:2181(CONNECTED) 34] create /node1 “node1” |
通过 create 命令在根目录创建了node1节点,与它关联的内容是数字 123
1 | [zk: 127.0.0.1:2181(CONNECTED) 1] create /node1/node1.1 123 |
1 | [zk: 127.0.0.1:2181(CONNECTED) 11] set /node1 "set node1" |
get 命令可以获取指定节点的数据内容和节点的状态,可以看出我们通过set 命令已经将节点数据内容改为 “set node1”。
1 | set node1 |
通过 ls 命令查看根目录下的节点
1 | [zk: 127.0.0.1:2181(CONNECTED) 37] ls / |
通过 ls 命令查看 node1 目录下的节点
1 | [zk: 127.0.0.1:2181(CONNECTED) 5] ls /node1 |
zookeeper 中的 ls 命令和 linux 命令中的 ls 类似, 这个命令将列出绝对路径path下的所有子节点信息(列出1级,并不递归)
通过 stat 命令查看节点状态
1 | [zk: 127.0.0.1:2181(CONNECTED) 10] stat /node1 |
上面显示的一些信息比如cversion、aclVersion、numChildren等等,我在上面 “ZNode(数据节点)的结构” 这部分已经介绍到。
ls2 命令更像是 ls 命令和 stat 命令的结合。ls2 命令返回的信息包括2部分:子节点列表 + 当前节点的stat信息。
1 | [zk: 127.0.0.1:2181(CONNECTED) 7] ls2 /node1 |
这个命令很简单,但是需要注意的一点是如果你要删除某一个节点,那么这个节点必须无子节点才行。
1 | [zk: 127.0.0.1:2181(CONNECTED) 3] delete /node1/node1.1 |
在后面我会介绍到 Java 客户端 API的使用以及开源 Zookeeper 客户端 ZkClient 和 Curator 的使用。
介绍该项目是做什么的、使用到了什么技术以及你对项目整体设计的一个感受
主要可以从下面三点来写:
以下均为我熟练使用的技能
自我发挥。切记不要过度自夸!!!
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢? JDK中提供的ThreadLocal类正是为了解决这样的问题。 ThreadLocal类主要解决的就是让每个线程绑定自己的值,可以将ThreadLocal类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。
如果你创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这也是ThreadLocal变量名的由来。他们可以使用 get() 和 set() 方法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题。
首先来代码:1
2
3
4
5
6
7public class TestPlusPlus {
public static void main(String[] args) {
int i = 0;
i++;
System.err.println(i);
}
}
然后执行 javap -c TestPlusPlus
脚踏实地,循序渐进
比如你想要做Web开发,那么可能就需要明确阶段性的目标,如先从前端或是后端的某个点着手,一点点拓展到其他的技术栈。
而一上手就要做高大上,就要采用“MEAN”(MongoDB+Express+Angular.js+Nginx)技术栈之类的,是不现实的。
在这几年的招聘过程中,个人感觉现在的前端圈子非常浮躁,很多毕业没两年的年轻人都会打上这样的标签:“精通jQuery”、“精通React”、“熟练使用xxx进行HTML5移动开发”之类的,笔试或者提问一些CSS基础、JS基础、简单算法都答不上来。会这些上层应用框架再多,也只是做一些代码的搬运工作,不太需要智商投入的事情,何来的底气要那么高的待遇?