关键字 synchronized 是 java 程序员在进入并发编程世界时的银弹,只要是遇到有并发访问安全的地方,会无脑的加上一个 synchronized 关键字进行修饰。但是随着对 java 并发编程的逐渐深入,我们也开始慢慢意识到 synchronized 是一个重量级的操作,曾经甚至有一段时间人们倡导使用 Lock 来代替 synchronized 关键字。不过 Lock 虽然灵活但也有其弊端,对开发人员写出线程安全且无死锁的多线程程序要求相对要提高了许多,好在 java 6 对 synchronized 关键字进行了大刀阔斧的优化,并推荐在 Lock 和 synchronized 均满足需求的场景下优先使用 synchronized 关键字。本文我们就一起来深入分析一下 synchronized 关键字的实现内幕。
Scala 集合:Map API
Map 定义了键值对的特质类型,区分可变与不可变,间接继承了偏函数 PartialFunction 特质,所以一个 Map 本质上也是一个偏函数,其定义如下:
1 | trait Map[K, +V] extends Iterable[(K, V)] with GenMap[K, V] with MapLike[K, V, Map[K, V]] |
其伴生对象提供了构造 Map 对象的简单方式,示例:
1 | val map1 = Map("name" -> "zhenchao", "age" -> 28) |
Scala 集合:Set API
Set 用于表示一个不包含重复元素的集合,不强调元素的顺序性。Set 同样被定义为是一个特质类型,区分可变与不可变,定义如下:
1 | trait Set[A] extends (A => Boolean) |
Scala 集合:Seq API
Seq 是一个特质类型(定义如下),用于表示按照一定顺序排列的元素序列,Seq 继承了偏函数 PartialFunction 特质,所以一个序列本质上也是一个偏函数,对应的函数类型是 Int => A,其中 A 是对应 Seq 的元素类型,而输入参数是 Seq 的下标。
1 | trait Seq[+A] extends PartialFunction[Int, A] |
Scala 集合:基础 API
Traversable 和 Iterable 特质定义了 scala 集合的基本操作,后续文章中将要介绍的 Seq、Set,以及 Map 等集合都实现了这两个特质。本文主要对 Traversable 和 Iterable 中定义的方法进行归类和介绍,了解这些方法也就基本知道了 scala 集合的大部分操作。
Traversable 定义为 Trait 类型,包含 2 个直接派生的子特质 mutable.Traversable 和 immutable.Traversable,分别表示可变集合和不可变集合。其中不可变集合是指集合中的元素一旦初始化完成便不可再被修改,任何对该集合的修改操作都将生成一个新的集合。Traversable 特质的定义如下:
1 | trait Traversable[+A] extends TraversableLike[A, Traversable[A]] |
那些年,面试被虐过的红黑树
- 面试官 :小桂子是吧,看你简历上写着精通 java 编程,想必对 java 已经掌握的很好了吧?
- 小桂子 :系呀系呀,一直都用 java 写 bug 呢~
- 面试官 :那你说说 jdk1.7 之前 HashMap 的底层实现原理呗,另外为什么在高并发场景下可能造成较高的 CPU 占用?
- 小桂子 :这个。。。好像是红黑树?
- 面试官 :哦?你说的是 jdk1.8 之后的设计,既然你提到了,那就聊聊红黑树这个数据结构吧,这里是白纸和笔,手写一棵吧!
- 小桂子 :哎呀,哎呀哎呀,老师,突然肚子好疼,我要去一下厕所,一会儿就回来~~~
OAuth 2.0 开放授权那些事儿
Dubbo 之于 SPI 扩展机制的实现分析
SPI (Service Provider Interfaces) 是 JDK 1.5 引入的一种服务扩展内置机制。在面向接口编程的范畴下,SPI 能够基于配置的方式声明应用的具体扩展接口实现。之前在写接口限流器时曾遇到过这样一个场景,针对服务端的限流策略一般需要从多个维度进行控制,比如具体接口、IP、用户、设备,以及调用方等等,假设限流器接口 org.zhenchao.spi.ApiRateLimiter 定义为:
1 | public interface RateLimiter { |
Reactor:事件驱动的高性能响应模式
Node.js 这几年火的不要不要的,借助 js 天生的事件驱动机制和 V8 高性能引擎,让编写高并发的 web 应用门槛降低了许多,当然这背后还要得益于 Douglas C. Schmidt 在 1995 年提出的基于事件驱动的 Reactor 模式,让本身只支持单线程执行的 js 能够胜任如今高并发环境下的服务端应用。
不过作为一名服务端开发人员,我对 js 的使用程度并不高,所以也一直没有机会去切身体会 Node.js 的魅力,好在 Reactor 只是一个设计模式,与具体语言和平台无关的。前段时间将负责的项目中的一个比较新的服务引入了 Vert.x 组件进行改造,也算是与 Reactor 模式有了一次亲密接触。Vert.x 是一个被称为运行在 JVM 上的 Node.js,用于在任何层次上编写非阻塞、响应式的模块或服务,关于 Vert.x 的发展历程还多少有些坎坷,具体可以移步官网。
限流技术中的常用算法及其优缺点
我们通常说缓存、降级,以及限流技术是高并发服务的三大利器,本文我们就来聊聊限流技术中常用的算法。为保证服务的可用性,限流往往是服务端接口的必备特性之一,用于对抗大规模恶意或无效请求,保护有限的计算和存储资源。关于接口限流有很多成熟的算法可供使用,包括:计数器、漏桶,以及令牌桶等,这些算法都为实际项目中的限流器设计提供了理论支撑。