期待你的分享

0%

Condition

Condition位于java.util.concurrent.locks包

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface Condition {
void await() throws InterruptedException;

void awaitUninterruptibly();

boolean await(long time, TimeUnit unit) throws InterruptedException;

boolean awaitUntil(Date deadline) throws InterruptedException;

void signal();

void signalAll();
}

Lock

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface Lock {
void lock();

void lockInterruptibly() throws InterruptedException;

boolean tryLock();

boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

void unlock();

Condition newCondition();
}

AbstractQueuedSynchronizer

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements Serializable{
protected AbstractQueuedSynchronizer() {
}

static class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;

final boolean isShared() {
return nextWaiter == SHARED;
}

final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null) {
throw new NullPointerException();
} else {
return p;
}
}

Node() {

}

Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}

Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}

private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;

protected final int getState() {
return state;
}

protected final void setState(int newState) {
state = newState;
}

protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

static final long spinForTimeoutThreshold = 1000L;

private Node enq(final Node node) {
for (; ; ) {
Node t = tail;
if (t == null) {
if (compareAndSetHead(new Node())) {
tail = head;
}
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}

private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}

private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}

private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0) {
compareAndSetWaitStatus(node, ws, 0);
}
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev) {
if (t.waitStatus <= 0) {
s = t;
}
}
}
if (s != null) {
LockSupport.unpark(s.thread);
}
}

private void doReleaseShared() {
for (; ; ) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) {
continue;
}
unparkSuccessor(h);
} else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) {
continue;
}

}
if (h == head) {
break;
}
}
}

private void setHeadAndPropagate(Node node, int propagate) {
Node h = head;
setHead(node);
if (propagate > 0 || h == null || h.waitStatus < 0 || (h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared()) {
doReleaseShared();
}
}
}

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waiteStatusOffset;
private static final long nextOffset;

static {
try {
stateOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
waiteStatusOffset =
unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("next"));
} catch (Exception ex) {
throw new Error(ex);
}
}

private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}

private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}

private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {
return unsafe.compareAndSwapInt(node, waiteStatusOffset, expect, update);
}

private static final boolean compareAndSetNext(Node node, Node expect, Node update) {
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}
}

场景

(本例子来自于设计模式之禅)

​ 在上小学的时候学校每次期末发成绩都会让家长签字,而这都会让一些学生十分头疼的事情,如果直接给家长看成绩,成绩考的不好家长又会说我们,但是又不能直接改成绩,如何解决呢?

阅读全文 »

  • 定义:

    责任链模式面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。 —维基百科

    阅读全文 »

Trie树

字典树、前缀树

image-20190826134606220

KMP算法

https://www.cnblogs.com/dusf/p/kmp.html

next数组:保存当前字符之前的字符串前缀和后缀最长重复子串长度

动态规划

dp数组

背包问题

有n个物品,物品对应的价值为W,费用是C,背包容量为V,每个物品只有一个可放可不放,求最大价值

1
2
3
for i in 0...n:
for j in 0...V:
dp[i][j] = max(dp[i-1][j], W[i]+dp[i-1][V-j])

AC自动机

红黑树

性质:

  1. 每个结点要么是红的,要么是黑的
  2. 根结点是黑的
  3. 每个叶结点是黑的
  4. 如果一个结点是红的,那么他的两个子结点是黑的
  5. 对于任意结点,其到叶结点NIL的每条路径都包含相同数量的黑结点

左旋

右旋

Manacher算法

用来求某个字符串的最长回文子串

https://blog.csdn.net/coraline_m/article/details/10002791

在进行某些网站的爬虫时,由于可能需要爬取的量特别大,比如像一些电商网站,这时我们可能加入一些分布式的东西,比如scrapy_redis组件实现了redis缓存的一些功能,但是可能由于一台主机的内存有限,任务量又太大,速率还是过慢,我们可能想到利用服务器和本机同时爬取,服务器端将爬取的内容存入主机的数据库,这时问题就来了,由于我的主机是处于路由器环境下,外网无法访问,如何能让外网连接到主机呢?经过一番查找和朋友的告知,可以利用ssh实现端口转发来达到目的。

阅读全文 »

[TOC]

STP(Spanning Tree Protocol)协议

生成树协议,逻辑上断开环路,防止二层网络的广播风暴产生

  • Root Bridge(根交换机):根
  • Designated Bridges(指定交换机):树枝
  • Bridge Protocol Data Unit(网桥协议数据单元)
  • Priority Vector(优先级向量)

网桥端口状态:阻塞、侦听、学习、转发、禁用

ICMP(Internet Control Message Protocol)协议

互联网控制报文协议

报文类型:查询报文类型,差错报文类型

image-20190822154552693

查询报文

ping命令:ICMP ECHO REQUEST + ICMP ECHO REPLY

image-20190822160546458

差错报文

终点不可达(3)

  • 网络不可达
  • 主机不可达
  • 端口不可达
  • 协议不可达
  • 需要进行分片但设置了不分片位

源抑制(4)

超时(11)

重定向(5)

Traceroute

  • 故意设置特殊的TTL,来追踪去往目的地时经过的路由器
  • 故意设置不分片,从而确定路径的MTU(Maximum Transmission Unit)

提问

  • 当发送的报文出问题的时候,会发送一个ICMP的差错报文来报告错误,但是如果ICMP的差错报文 也出问题了呢?
  • 这一节只说了一个局域网互相ping的情况。如果跨路由器、跨网关的过程会是什么样的呢?

如何上网

网关Gateway:往往是路由器,三层转发设备(把MAC头和IP头都取下来,根据内容决定往哪里转发的设备)

路由器是一个设备,有多个网卡,每个网卡都是一个网关

静态路由、动态路由

不改变IP地址的网关,我们称为转发网 关;改变IP地址的网关,我们称为NAT网关。

NAT网关(Network Address Translation):IP会变

UDP协议

TCP协议

image-20190919175146155

解决5个问题:

  • 顺序问题
  • 丢包问题
  • 连接维护
  • 流量控制
  • 拥塞控制

image-20190919175328021

发送端窗口状态:

image-20190919175838450

接收端窗口状态:

image-20190919175942574

Socket

基于TCP的socket连接协议

image-20190926215649617

image-20190926215951462

基于UDP的socket连接协议

image-20190926220040568

网络

DNS解析过程

  1. 浏览器输入域名http://www.baidu.com ,操作系统会先检查hosts文件是否有这个网址的映射关系,如果有,就先调用这个IP,完成域名解析
  2. 如果hosts里面没有,则查找本地DNS解析器缓存,是否有这个网址的映射关系,如果有,就先调用这个IP,完成域名解析
  3. 如果还是没有,则会查找TCP/IP参数中设置的首选DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置的区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性
  4. 如果要查询的域名不由本地DNS服务器区域解析,但该服务器已经缓存了此网址映射关系,则调用这个IP地址映射,此解析不具有权威性
  5. 如果本地DNS服务器区域解析与缓存都失效,则根据本地服务器的设置(是否设置转发器)进行查询,如果未用转发器模式,本地DNS就把请求发送给13台根DNS,根DNS收到请求后会判断这个域名(.com)是谁来授权管理,并返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP后,将会请求这台服务器,如果这台服务器自己无法解析,它就会找一个管理.com域名的下一级DNS服务器地址(http://baidu.com)给本地DNS服务器。当本地服务器收到地址后,就会找http://baidu.com域服务器,重复上面的动作,进行查询,知道找到www.baidu.com的主机
  6. 如果用的是转发模式,此DNS服务器就会把请求转发给上一级服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把请求转发给上上级,以此循环。不管本地DNS服务器用的是转发,还是根提示,最后都是把结果返回给本地DNS服务器,再由本地DNS服务器返回给客户机。

请求过程用的是UDP还是TCP?

UDP,UDP发送快

为什么是13台根服务器?

为了做Prime QueryRoot Servers性价比达到最高,肯定是一个包能放多少东西就塞多少东西,所以把所有Root Servers的结果都塞进去,刚好能塞14个,不全用就塞13个吧,留下一点东西以备后患,留待扩展。

I/O

同步、异步:消息通信机制

阻塞,非阻塞:等待状态

五种I/O模型:

  • 阻塞I/O
  • 非阻塞I/O
  • I/O多路复用
  • 信号驱动I/O
  • 异步I/O

select函数

多路复用I/O

1
int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout);

机制

select提供一个fd_set数据结构,实际上是一个long型的数组,里面的每个元素都与能打开的文件句柄建立联系,当调用select时,由内核根据IO状态修改fd_set的内容,由此通知select()的进程某个socket或文件可读

优点

一个线程处理多个I/O请求

问题

  1. 每次调用select时,都要把fd_set集合 从用户态拷贝到内核态,开销大
  2. 每次调用select时,都要遍历一遍fd_set集合,时间长
  3. 为了减少数据拷贝带来的性能损耗,fd_set的集合大小有限制,限制为1024(不可改变)

poll函数

1
2
3
4
5
6
7
int poll(struct pollfd *fds, nfds_t nfds, int timeout);

typedef struct pollfd {
int fd; // 需要被检测或选择的文件描述符
short events; // 对文件描述符fd上感兴趣的事件
short revents; // 文件描述符fd上当前实际发生的事件
} pollfd_t;

与select类似,但是没有大小限制

epoll函数

事件驱动I/O

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 创建一个epoll句柄,size代表描述符数量,成功时返回epoll句柄描述符,失败时返回-1
int epoll_create(int size);
// 注册要监听的事件类型:注册,修改,删除
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
// 等待事件的就绪,成功时返回就绪的事件数目,失败时返回-1,等待超时返回0
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;

epoll没有描述符个数限制,使用一个文件描述符管理多个描述符,将用户关心的文件描述符的事件存放到内核的一个事件表中,这样用户态和内核态的空间拷贝只需一次

触发方式:

  • 水平触发(LT):默认,当epoll_wait检测到某描述符事件就绪并通知应用程序时,应用程序可以不立即处理;下次调用epoll_wait时,会再次通知该事件(1->1)
  • 边缘触发(ET):当epoll_wait检测到某描述符事件就绪并通知应用程序时,应用程序必须处理该事件;如果不处理,下次调用epoll_wait时,不会通知该事件。(直到其他操作导致该描述符变为未就绪状态时,也就是边缘触发只在状态从未就绪到就绪通知一次)(0->1)

场景

(本例子来自于Head First 设计模式)
假如我们现在经营着一家披萨店,那么我们需要提供多种不同口味的披萨供用户选择,那么我们可能会这样做:

阅读全文 »