看完这部电影,不得不说,最后被男主拿出的戒指感动到了~戒指没有不见,它一直在那里。
回想女主第一次拒绝结婚的理由让人熟悉而又无奈,这不是我们每个男生都害怕听到的理由吗?

我还没有准备好

幸好,最后结局有情人终成眷属了。回想起剧情,就像溪水,可能会流的慢,但是总会流到那里。

最后女主结婚的理由才像她自己:

阅读全文 »

1 炒鸡蛋与对称密码

鸡蛋炒好之后就完全分不清原来的蛋黄和蛋白了,使用对称密码进行加密,和炒鸡蛋有着异曲同工之妙。炒鸡蛋搅拌的是鸡蛋,而密文打乱的则是比特序列。
然后,它们最大的不同是,炒鸡蛋无法还原成原来的鸡蛋,但密文却必须能够让接收者正确解密才行。
因此,如果只是随意地搅拌和混合,则不能称之为加密,而必须仔细设计出一种能够还原的混合方式。

阅读全文 »

1 本章概要

本章将介绍历史上几种著名的密码:

  1. 凯撒密码
  2. 简单替换密码
  3. Enigma

此外,还介绍两种破译密码的方法:

  1. 暴力攻击
  2. 频率分析

最后,我们还将思考密码算法与密钥之间的关系。
本章所介绍的密码在现在都已经不再适用了,但在寻找密码弱点的方法、破译密码的思路以及密码算法与密钥的关系等方面,这些密码与现在密码技术依然是相通的。

阅读全文 »

1 本章概要

从整体上了解密码世界的模样。

2 密码

2.1 Alice 与 Bob

要讲解密码,需要给参与信息交互的人和计算机起几个名字,如下表:

名称 说明
Alice 一般角色
Bob 一般角色
Eve 窃听者,可窃听通信内容
Mallory 主动攻击者,可妨碍正常通信、伪造消息等
Trent 可信的第三方
Victor 验证者
阅读全文 »

1 Lock 接口

2. 队列同步器

队列同步器 AbstractQueueSynchronizer (简称同步器),是用来构建锁或者其它同步组件的基础框架,它使用了一个 int 成员变量表示同步状态,
通过内置的 FIFO 队列完成资源获取线程的排队工作。

2.1 队列同步器的接口与示例

同步器是实现锁(也可以是任意同步组件)的关键,在锁的实现中聚合同步器,利用同步器实现锁的语义。可以这样理解二者的关系:锁是面向使用者,
它定义了使用者与锁交互的接口,隐藏了实现细节;同步器面向的是锁的实现者,它简化了锁的实现方式,屏蔽了同步状态管理、线程的排队、等待与唤醒等底层操作。
锁和同步器很好地隔离了使用者和实现者所需关注的领域。

阅读全文 »

1 等待多线程完成的 CountDownLatch

例如:解析一个 Excel 里多个 sheet 的数据,如果使用多线程,每个线程解析一个 sheet 里的数据,等到所有的 sheet 都解析完之后,程序提示解析完成。

即,需要主线程等待所有线程完成 sheet 的解析操作,最简单的做法是使用 join() 方法,代码8-1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class JoinCountDownLatchTest {
public static void main(String[] args) throws Exception {
Thread parser1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("parser1 finish");
}
});
Thread parser2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("parser2 finish");
}
});
parser1.start();
parser2.start();
parser1.join();
parser2.join();
System.out.println("all parser finish");
}
}

阅读全文 »

1 ConcurrentHashMap 的实现原理与使用

1.1 为什么要使用 ConcurrentHashMap

  1. 线程不安全的 HashMap ,在多线程下 HashMap 的 Entry 链表导致形成环形数据结构, Entry 的 next 节点永远不为空,就会产生死循环获取 Entry 。
  2. 效率低下的 HashTable ,使用 synchronized 保证线程安全。
  3. ConcurrentHashMap 的锁分段技术有效提升并发访问率。 HashTable 效率低下是因为所有访问 HashTable 的线程都必须竞争同一把锁,如果容器里
    有多把锁,每把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程就不会存在锁竞争。
阅读全文 »

1 线程简介

1.1 什么是线程

操作系统运行一个程序时,会为其创建一个进程。而操作系统调度的最小单元是线程,也叫轻量级进程( Light Weight Process),
在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。
处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MultiThread{
public static void main(String[] args) {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
for(ThreadInfo threadInfo : threadInfos) {
System.out.println(threadInfo.getThreadId() + "," + threadInfo.getThreadName());
}
/**
6,Monitor Ctrl-Break
5,Attach Listener
4,Signal Dispatcher
3,Finalizer
2,Reference Handler
1,main
*/
}
}

阅读全文 »

1 数据发布/订阅

数据发布/订阅(Pulish/Subscribe)系统,即所谓的配置中心,顾名思义就是发布者将数据发布到ZooKeeper的一个或一系列节点上,供订阅者进行数据订阅, 进而达到动态获取数据的目的,实现配置信息的集中式管理和数据的动态更新。

发布/订阅系统一般有两种设计模式,分别是推(Push)模式和拉(Pull)模式。在推模式中,服务端主动将数据更新发送给所有订阅的客户端;而拉模式则是由 客户端主动发起请求获取最新数据,通常客户端都采用定时进行轮询拉取的方式。ZooKeeper采用的是推拉结合的方式:客户端向服务端注册自己需要关注的 节点,一旦该节点的数据发生变更,那么服务端就会向相应的客户端发送Watcher事件通知,客户端接收到这个消息通知之后,需要主动到服务端获取最新的数据。

阅读全文 »

本章概要:
首先对ZooKeeper进行一个整体上的介绍,包括ZooKeeper的设计目标、由来以及它的基本概念,然后将会重点介绍ZAB这一ZooKeeper中非常重要的一致性协议。

1. 初识ZooKeeper

1.1 ZooKeeper介绍

ZooKeeper由雅虎创建,是Chubby的开源实现。设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。

阅读全文 »