ARTS-WEEK-008
Algorithm:
96: Unique Binary Search Trees (Medium)
这道题有几个关键点,1首先需要充分理解 BST 二叉搜索树,左子树都小于、右子树都大于当前节点,因此每确定一个根节点,其种类数可以固定计算,等于左子树种类数乘以右子树种类数。2抽象和推导出递归公式,g(n) 代表数量为n个节点的树的种类数(即题目要求的 1 到 n节点),f(i, n) 代表数量为n个节点的树中,以其中某节点 i 为根时的树的种类数。于是 g(n) = ∑ f(i, n), 而 f(n) = g(i - 1) * g(n - i),整体推导出 g(n) = ∑ g(i - 1) * g(n - i)。3最后一点,利用动态规划思想,递归公式可以转化为从下到上的递推形式,这里技巧是观察求和公式,每个 g(n) 都依赖 g(n-1),反过来想就是可以从小到大依次计算,结果放到 memo 中复用。
public int numTrees(int n) {
// g(n) = g(0)*g(n-1) + g(1)*g(n-2) + ... + g(n-1)*g(0)
int[] memo = new int[n + 1];
memo[0] = 1;
memo[1] = 1;
for (int i = 2; i < n + 1; i++) {
for (int j = 0; j < i; j++) {
memo[i] += memo[j] * memo[i - j - 1];
}
}
return memo[n];
}
Review:
Happens-Before 关系,比如 A happens-before B,并不是时间关系,不是现实中的前后顺序关系,仅仅是语言规范中的一种概念,这是一种担保,即 A 对内存的影响对 B 是一定可见的。只有当语言规范规定了什么情况下保证 happens-before 时我们才能确保可见性,除此之外一切都是不确定的。最基本的一个 happens-before 关系是同一线程中 A 语句在 B 语句之前,则 A happens-before B。
文中举出了两个典型的例子,分别是:1有 happens-before 关系但程序(汇编指令)实际先执行后者;2两个线程中程序 A B 和 C D 执行顺序都已确定时,比如 C 通过 IF 判断道 B 已执行,但是 D 依然可能读到 A 没有执行的情况,因为 A D 之间没有 happens-before 关系。
Tip:
一次服务端出现大量 CLOSE_WAIT 连接的分析
总结去年的一次线上问题,一个高 TPS 的应用增加了发送MQ逻辑后,在请求高峰时个别机器出现请求处理缓慢(TP99飙升到几十秒几百秒)、CPU 使用率飙升、网络连接中 CLOSE_WAIT 数量飙升到8000,最后新的请求无法处理新请求,形成 TOMCAT 卡死的状态,该实例重启后可以恢复,但是不断有其他实例出现这样的问题,最后选择关闭 MQ 发送后问题解决。
首先每个请求都会调用发送 MQ 方法,因为用的是异步发送方式觉得不会影响主逻辑,但是这里肯定有问题,通过源码跟踪,异步发送是指使用 netty 同步的 channel.writeAndFlush().addListener(xx) 后就结束逻辑,通过 Linstener 异步接收 Broker 返回的 ACK 信息,如果有各种原因导致发送太慢就会形成反压,这里应该通过带有抛弃策略线程池和队列发送消息,确保不影响主流程。但是有一个一直不明白的地方是为什么产生那么多 close_wait,以及为什么 tomcat 不会释放连接,导致新连接进不来?
首先 close_wait 在 TCP 关闭图中处于右侧,是被动关闭时发送完对方 FIN 的 ACK 后,进入释放资源的阶段,之后再发送自己的 FIN 通知对方自己要关闭。这里因果链是 MQ 发送问题,导致 http 请求处理慢,当达到对方 client 的超时后,对方关闭连接,于是我们成为被关闭方,而此时 TOMCAT 不会因为收到 FIN 就 Kill 该线程,导致该连接因为 MQ 积压始终占用着,业务一直处理中,很快就把 TOMCAT 业务线程用完!但是实际上TOMCAT 业务线程池有 350 个,established 有 350 个,而 close_wait 有 8000 多个,这里要考虑 TOMCAT 到底是如何使用 NIO 处理和关闭连接了。
Share:
What is Timeboxing? 5 Questions (and Answers) About This Productivity Strategy
时间盒方法强调安排任务计划时不是以待办项作为主体、而是以时间段作为主体。比如在清单中列出要做的A、B、C这是传统的方法,时间盒方法则是列出 A - 2 * 30分钟、B - 1 * 30 分钟、C - 3 * 30分钟这类清单。这样在时间开始后专心完成事项并在每个时间盒结束时重新评估,当无法完成时不断尽力调整,以求完成最重要和最核心的部分,舍弃其他部分。
该方法最优价值的地方在于:1 帮助专注,2 避免困难任务拖延或庞大任务无法启动,3 不断评估,帮助改进,关注价值,4 避免一个任务无法完成影响其他任务。