阻塞,非阻塞,同步,异步概念理解

对于阻塞,非阻塞,同步,异步这几个概念,心里知道意思,但是要仔细讲出来发现又不是那么容易。

严重参考并组合了以下几篇文章。

Linux IO模式及 select、poll、epoll详解

怎样理解阻塞非阻塞与同步异步的区别

我们知道应用程序是跑在用户空间的,对一次 IO 访问,比如 read, 实际上是数据首先被拷贝到操作系统内核的缓冲区,然后才是从内核的缓冲区拷贝到用户空间应用程序的地址空间。所以一个 read 操作会尽力两个阶段:

  1. 等待数据准备 (Waiting for the data to be ready)
  2. 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)

UNIX 网络编程卷一 中列举了五种 I/O 模型。

  • 阻塞 I/O(blocking IO)
  • 非阻塞 I/O(nonblocking IO)
  • I/O 多路复用( IO multiplexing)
  • 信号驱动 I/O( signal driven IO)
  • 异步 I/O(asynchronous IO)

更多

hibernate-search-elasticsearch 集成

近期将 elasticsearch 集成到了系统里面, 做一些记录

jpa hibernate-search 集成

为了让框架能够自动维护索引(创建,更新,删除),需要手动写一个 AOP 框架,在实体维护的时候同时维护索引。发现 hibernate 官方的 hibernate-search-elasticsearch 已经做了这块儿工作了,开心。

我这里使用的是 JPA 所有的配置如下:

部分 pom.xml 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<properties>
<hibernate.core.version>5.1.3.Final</hibernate.core.version>
<hibernate.search.version>5.6.0.Final</hibernate.search.version>
<hibernate.search.elasticsearch.version>5.6.0.Final</hibernate.search.elasticsearch.version>
</properties>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-elasticsearch</artifactId>
<version>${hibernate.search.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>${hibernate.search.version}</version>
</dependency>

这里有 2 个坑:

  1. hibernate core 的版本不要太高,如果使用 hibernate 5.2 以上的版本,都会出现和 hibernate search 不相容的错,Hibernate 5.2 is not compatible with any version of hibernate search

  2. 必须添加 hibernate search orm 支持,不然无法自动创建索引

实体映射

春节读书计划

难得放假,读读书也是不错的。过年也就这么几天,准备读这几本书。

  • 大话处理器:处理器基础知识读本

这本到今天已经读完,算是提前完成任务了。作为入门级的读本,本书幽默风趣,真是在适合不过。

大话处理器:处理器基础知识读本

  • Java并发编程的艺术

草草翻了2章,不点到为止,系统化从底层讲起应该算是本书区别于市面上其它书籍的显著特征。

Java并发编程的艺术

  • 实战Java虚拟机:JVM故障诊断与性能优化

读过周志明的深入理解Java虚拟机:JVM高级特性与最佳实践(第1版)
个人感觉,还是葛一鸣写得更加简单明了

实战Java虚拟机:JVM故障诊断与性能优化

春节期间的任务就是读书,带娃,串门。

JAVA 8 学习总结

最近一周 JAVA8 的学习总结

Lambda 表达式

  • Predicate

方法: boolean test(T t)
函数描述: T -> boolean
作用: 传入一个参数,返回一个bool结果
特征化原始类型: IntPredicate, LongPredicate, DoublePredicate

  • Consumer

方法: boolean test(T t)
函数描述: T -> void
作用: 传入一个参数,返回一个bool结果
特征化原始类型: IntPredicate, LongPredicate, DoublePredicate

  • Function

方法: R apply(T t)
函数描述: T -> R
作用: 传入一个参数,返回一个结果
特征化原始类型: IntFunction, IntToLongFunction, IntToDoubleFunction, LongFunction, LongToIntFunction, LongToDoubleFunction, DoubleFunction, ToIntFunction, ToLongFunction, ToDoubleFunction

  • Supplier

方法: T get()
函数描述: () -> T
作用: 无参数传入,返回一个结果
特征化原始类型: BooleanSupplier, IntSupplier, LongSupplier, DoubleSupplier

更多

位移运算与运算的基本作用

最近看了很多底层代码,大量使用到了基础的位移,与运算等,做一个总结。

位移与运算基础知识

  1. 数字在计算机中是以 补码 的形式保存的;正数的原码,补码,反码相同;负数的补码是原码取反加 1 得到的

  2. 位移操作涉及到类型转换

假设有 x << n

  • x 是 byte short char int long 基本类型, n 只能是 int 类型

  • 若 x 是 byte short char 类型,首先将类型转化为 int 然后才进行位移操作

  • 若 x 是 byte short char int 类型,那么 n 会被重新赋值,计算方法是 n % 32,可以理解为超过如果 n 超过 32 进行取模

    取 n 的补码的低 5 位, 然后转换为十进制的 int 值,相当于对 n 取 32 模: n = n % 32

    为什么是 5,int 占用 32 位,刚好是 2 的 5 次方

  • 若 x 是 long 类型,取 n 的补码的低 6 位, 计算 n 的方法是 n % 64

  • double float 类型不能进行移位运算

  1. 左移运算 <<

按照二进制方式将所有的数字向左移动对应的位数,高位舍弃,低位补 0 ;左移有可能导致溢出。

数学意义:在没有溢出的情况下,对于 正数 和 负数, 左移一位相当于乘以 2 的 1 次方,移动 n 位相当于乘以 2 的 n 次方。

  1. 有符号右移运算 >>
    按照二进制形式把所有的数字向右移动对应的位数,低位舍弃,高位的空位补符号位,即正数补 0 ,负数补 1

数学意义:右移一位相当于除以 2 ,右移 n 位相当于除以 2 的 n 次方, 取商,不要余数。

  1. 无符号右移运算 >>>
    按照二进制方式把所有的数字向右移动对应位数,低位舍弃,高位空位补 0

更多

java 基础 ----基本数据结构

基本数据类型

  • 字符型(char)

java 采用 unicode 编码, 使用 2 个字节表示一个字符,所以java中的一个字符是 2 个字节
c 语言使用的是 ASCII 编码,一个 char 占用 1 个字节。

由于是无符号的,且 2 个字节 32 位长度,那么其范围是 0 到 65535 。

  • 布尔类型: boolean

  • 数值类型: 有符号数值类型,最高位表示符号位
    byte : 1 字节
    short : 2 字节
    int : 4 字节
    long : 8 字节
    float : 4 字节
    double : 8 字节

更多

编辑器之 tmux

install

mac 上安装

1
brew install tmux

需要使用的时候只需要在命令行输入 tmux
tmux 所有的操作都带了一个 prefix , 这也是 tmux 用起来比较麻烦的地方. 默认的 prefix 是 ctrl + b

session

直接在终端查看 session 相关信息

1
2
3
4
tmux ls 列出会话
tmux attach -t session 进入某个会话
tmux -r 连接上个断开的session
tmux new -s session -d 在后台建立会话

进入 tmux 后查看 session 相关信息

1
2
3
ctrl+b s 查看/切换session
ctrl+b d 离开(detach)session
ctrl+b $ 重命名当前session

更多

JAVA ClassLoader

java 类加载器概述

要使用一个类必须要先将这个类加载到内存中, JVM 将编译后的字节码文件, 即 .class 文件加载到内存中, 并生成一个 java.lang.Class 对象.

字节码文件通常有一下来源:

  • 本地磁盘文件系统 class 文件
  • JAR 包中加载 class 文件
  • 网络地址加载 class 文件
  • 动态编译一个 java 源文件, 并执行加载

类加载器

java 中的类加载器是通过双亲委派模型来实现的, 有如下特点

  • 类的加载过程采用委托模式实现. 某个特定的类加载器在接到加载类的请求时, 首先将加载任务委托给父类加载器, 依次递归, 如果父类加载器可以完成类加载任务, 就成功返回; 只有父类加载器无法完成此加载任务时, 才自己去加载.

  • JVM 预定义了三种类加载器

    • 根类加载器(Bootstrap ClassLoader). 由C++实现, 负责将<Java_Runtime_Home>/lib下面的类库加载到内存中, 如 rt.jar
    • 扩展类加载器(Extension ClassLoader). 负责将 <Java_Runtime_Home >/lib/ext 或者由系统变量 java.ext.dir指定位置中的类库加载到内存中. 开发者可以直接使用标准扩展类加载器.
    • 系统类加载器(System ClassLoader). 负责将系统类路径(CLASSPATH)中指定的类库加载到内存中. 开发者可以直接使用系统类加载器。