ARTS 05

  • Algorithm [剑指offer] 丑数
  • Review Google如何跟踪您的个人信息
  • Tip TCP的TIME_WAIT机制
  • Share ConcurrentHashMap1.8实现

Algorithm [剑指offer] 丑数

本题是来自牛客网的【剑指Offer】中的丑数,其在互联网公司校招出现概率较大,建议尝试做一做。

题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

public int GetUglyNumber_Solution(int index) {
        if(index <= 0)
            return 0;
        if(index == 1)
            return 1;
        int t2 = 0, t3 = 0, t5 = 0;
        int [] res = new int[index];
        res[0] = 1;
        
        for(int i = 1; i

解题思路
我们只求丑数,不要去管非丑数。每个丑数必然是由小于它的某个丑数乘以2,3或5得到的,这样我们把求得的丑数都保存下来,用之前的丑数分别乘以2,3,5,找出这三这种最小的并且大于当前最大丑数的值,即为下一个我们要求的丑数。这种方法用空间换时间,时间复杂度为O(n)。


Google如何跟踪您的个人信息

每次互联网搜索都包含关键字,而您刚刚输入Google的关键字则由广告客户进行争夺。每个提供与您的关键字相关的产品的广告客户都希望看到并点击其广告。

点击广告后,您的信息会传递给搜索引擎营销人员,并将其永久存储在AdWords帐户中,永远不会被删除。
只要您使用Google,Google一直在为您构建“公民资料”。

搜索引擎营销的圣杯:多设备归属。当这项技术得以实现时,广告将无缝地跟踪搜索者 - 不仅跨渠道(例如,社交,有机和电子邮件),而且跨设备(例如,从移动设备到平板电脑,从笔记本电脑到电视再到桌面)。

在手机上搜索产品,然后亲自走进商店。按此顺序执行此操作,Google可能会使用您手机的GPS数据来关联您的广告点击和店内购买。

今天,人们告诉谷歌他们在其他地方承认的事情 - 不是他们的配偶,医生或缩水。但是如果谷歌用户了解这个兔子洞有多远,他们就不会对搜索引擎这么直率。有了我将提供的内幕信息,我希望读者可以回到谷歌不是唯一可以告诉他们的恐惧,遗憾,希望和梦想的地方。


TCP的TIME_WAIT机制

TIME_WAIT的产生条件:主动关闭方在发送四次挥手的最后一个ACK会变为TIME_WAIT状态,保留次状态的时间为两个MSL(linux里一个MSL为30s,是不可配置的)

TCP.jpg

TIME_WAIT两个MSL的作用:可靠安全的关闭TCP连接。比如网络拥塞,主动方最后一个ACK被动方没收到,这时被动方会对FIN开启TCP重传,发送多个FIN包,在这时尚未关闭的TIME_WAIT就会把这些尾巴问题处理掉,不至于对新连接及其它服务产生影响。

MSL概念:MSL指的是报文段的最大生存时间,如果报文段在网络活动了MSL时间,还没有被接收,那么会被丢弃。

TIME_WAIT占用的资源:少量内存(查资料大概4K)和一个fd。

TIME_WAIT关闭的危害:

  • 1、 网络情况不好时,如果主动方无TIME_WAIT等待,关闭前个连接后,主动方与被动方又建立起新的TCP连接,这时被动方重传或延时过来的FIN包过来后会直接影响新的TCP连接;

  • 2、 同样网络情况不好并且无TIME_WAIT等待,关闭连接后无新连接,当接收到被动方重传或延迟的FIN包后,会给被动方回一个RST包,可能会影响被动方其它的服务连接。

TCP: time wait bucket table overflow产生原因及影响:原因是超过了linux系统tw数量的阀值。危害是超过阀值后﹐系统会把多余的time-wait socket 删除掉,并且显示警告信息,如果是NAT网络环境又存在大量访问,会产生各种连接不稳定断开的情况。

解决办法:

  • 可以尝试缩小它的设置,比如十秒,甚至一秒,具体设置成多少合适取决于网络情况而定,当然也可以参考相关的案例。

  • TIME_WAIT总是在关闭发起方产生,服务端资源有限,可能同时连接上万个连接,所以尽量由客户端发起关闭请求,这样产生的就都在客户端

  • tcp_tw_recycle:顾名思义就是回收TIME_WAIT连接。可以说这个内核参数已经变成了大众处理TIME_WAIT的万金油,如果你在网络上搜索TIME_WAIT的解决方案,十有八九会推荐设置它,不过这里隐藏着一个不易察觉的陷阱:
    当多个客户端通过NAT方式联网并与服务端交互时,服务端看到的是同一个IP,也就是说对服务端而言这些客户端实际上等同于一个,可惜由于这些客户端的时间戳可能存在差异,于是乎从服务端的视角看,便可能出现时间戳错乱的现象,进而直接导致时间戳小的数据包被丢弃。参考:tcp_tw_recycle和tcp_timestamps导致connect失败问题。

  • tcp_max_tw_buckets:顾名思义就是控制TIME_WAIT总数。官网文档说这个选项只是为了阻止一些简单的DoS攻击,平常不要人为的降低它。如果缩小了它,那么系统会将多余的TIME_WAIT删除掉,日志里会显示:「TCP: time wait bucket table overflow」。

需要提醒大家的是物极必反,曾经看到有人把「tcp_max_tw_buckets」设置成0,也就是说完全抛弃TIME_WAIT,这就有些冒险了,用一句围棋谚语来说:入界宜缓。

ConcurrentHashMap1.8实现

JDK1.8版本的ConcurrentHashMap的数据结构已经接近HashMap,相对而言,ConcurrentHashMap只是增加了同步的操作来控制并发,从JDK1.7版本的ReentrantLock+Segment+HashEntry,到JDK1.8版本中synchronized+CAS+HashEntry+红黑树,相对而言,总结如下思考:

  • JDK1.8的实现降低锁的粒度,JDK1.7版本锁的粒度是基于Segment的,包含多个HashEntry,而JDK1.8锁的粒度就是HashEntry(首节点)
  • JDK1.8版本的数据结构变得更加简单,使得操作也更加清晰流畅,因为已经使用synchronized来进行同步,所以不需要分段锁的概念,也就不需要Segment这种数据结构了,由于粒度的降低,实现的复杂度也增加了
  • JDK1.8使用红黑树来优化链表,基于长度很长的链表的遍历是一个很漫长的过程,而红黑树的遍历效率是很快的,代替一定阈值的链表,这样形成一个最佳拍档
  • JDK1.8为什么使用内置锁synchronized来代替重入锁ReentrantLock,我觉得有以下几点:
  1. 因为粒度降低了,在相对而言的低粒度加锁方式,synchronized并不比ReentrantLock差,在粗粒度加锁中ReentrantLock可能通过Condition来控制各个低粒度的边界,更加的灵活,而在低粒度中,Condition的优势就没有了
  2. JVM的开发团队从来都没有放弃synchronized,而且基于JVM的synchronized优化空间更大,使用内嵌的关键字比使用API更加自然
  3. 在大量的数据操作下,对于JVM的内存压力,基于API的ReentrantLock会开销更多的内存,虽然不是瓶颈,但是也是一个选择依据

参考文献:
理解TIME_WAIT,彻底弄清解决TCP: time wait bucket table overflow
TIME_WAIT原理
TCP/IP详解--TIME_WAIT状态存在的原因
面试总结之time_wait状态产生的原因,危害,如何避免
ConcurrentHashMap1.8实现
ConcurrentHashMap1.7实现
为并发而生的 ConcurrentHashMap(Java 8)

你可能感兴趣的:(ARTS 05)