Hashmap源码解析-与hashtable区别

HashMap是非线程安全的,HashTable是线程安全的。

Hashmap源码解析-get

get

查找过程和删除基本差不多, 找到返回节点,否则返回null

Hashmap源码解析-扩容函数

系列目录

  1. 总览&目录
  2. 链表节点NODE
  3. 构造函数
  4. 扩容函数
  5. put
  6. remove
  7. get
  8. 遍历
  9. &hashtable

扩容函数

1.更新容量和阈值,

​ if cap>0, 不超过上限的情况下cap、thre都乘2

​ if cap=0, oldThr>0, 说明初始化的时候赋初始容量参数了,newCap=oldThr

​ if cap=0, oldthr=0, 直接重新初始化,cap=16,thre=12

2.更新哈希桶, 遍历原桶

​ if 只有一个节点,直接挪过去

​ if 链表有超过8个节点,是红黑树, 复杂, 再说todo

​ if 少于8个的链表,则可能挪到低位,也可能挪到高位,看它本身hash在新容量时应在哪里,代码中巧妙通过与oldCap & 的方式判断需改到高还是低,具体在代码注释中有

Hashmap源码解析-put

源码解析-put函数

Hashmap源码解析-remove

remove

1.找到待删除节点,也是分第一个节点就是,红黑树中找该节点,普通链表中找该节点

2.删除节点,分红黑树删除,头节点删除,中间节点删除(包括尾)

3.++modCount, –size

concurrentmodificationexception源码解析

Java安全开发手册中
  • 7. 【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。
个人总结
  • 在迭代器中走list的remove大部分情况都会抛 ConcurrentModificationException 异常,从迭代器的next、remove中抛出,因new迭代器类的时候,私有变量expectedModCount会记录修改次数,当List的modCount不一致时会抛出异常,而List的add,remove等修改操作都会增加modCount

  • 也会有在删除某些元素后导致迭代器cursor和size正好相等,hasnext返回false, 不再遍历就不抛异常,但不会遍历到后面移动到已删除位置的元素

  • List接口中有iterator()接口,因此List的子类都要注意这点

当在浏览器输入google.com回车的时候发生了什么

当在浏览器输入google.com回车,根据github库中的分析,会发生24个过程,我们去除其中物理电路和部分前端、windows系统等步骤,将我们关心的步骤进行分析

一、解析输入#

  1. 解析获取协议、主机名、资源地址

  2. 根据协议和主机名判断文字是URL还是搜索关键字,if url: 3, if not url: 文字传给默认的搜索引擎

  3. 如果主机名部分含有非ASCII字符, 浏览器会对主机名部分使用 Punycode 编码

二、建立连接#

  1. 检查预加载 HSTS(HTTP严格传输安全)列表#
    1. 是否必须使用https请求,避免第一次非https请求
  2. DNS查询#
    1. 查看 Chrome 缓存是否存在
    2. 调用 gethostbyname函数
      1. 是否在本地hosts文件,是 返回,否 ii
      2. 向本地DNS服务器发送请求,使用 53 端口向 DNS 服务器发送 UDP 请求包,如果响应包太大,会使用 TCP 协议,本地DNS服务器可能是在内网中,或者是在ISP的机房中
        1. 内网中的话直接ARP就可以找到MAC地址,就可以发DNS请求过去
        2. 外网ISP机房DNS服务器的话,也需ARP找到网关的MAC, 发送到网关,源MAC地址永远为客户端MAC地址,源IP通过NAT将内网IP转为外网IP加指定端口号, 目的MAC通过路由协议转为下一跳路由MAC, 目的IP为ISP外网IP, 数据包一直路由到ISP的网关,根据目的IP和端口号经过NAT转换包目的IP为内网dns ip, 通过ARP或缓存,目的mac改为dns服务器mac,发送请求至ISP dns服务器
      3. if 本地/ISP DNS 服务器找到结果,返回结果,if not: iv
      4. if 支持转发,它会发送一个递归查询请求,可能会一层一层向高层 DNS 服务器做查询,直到查询到起始授权机构,把结果返回
      5. 也可能本身不支持转发, 或向上查询过程中某DNS服务器不支持转发,则会开始进行迭代查询,通过先后查询根、顶级、权威dns服务获取对应ip
  3. TCP封包#
    1. 当浏览器得到了目标服务器的 IP 地址,以及 URL 中给出来端口号(http 协议默认端口号是 80, https 默认端口号是 443),它会调用系统库函数 socket ,请求一个 TCP流套接字
    2. 请求首先被交给传输层,在传输层请求被封装成 TCP segment。目标端口会被加入头部,源端口会在系统内核的动态端口范围内选取
    3. TCP segment 被送往网络层,网络层会在其中再加入一个 IP 头部,里面包含了目标服务器的IP地址以及本机的IP地址,把它封装成一个IP packet
    4. 接下来会进入链路层,链路层会在封包中加入 frame 头部,里面包含了本地内置网卡的MAC地址以及网关(本地路由器)的 MAC 地址。如果不知道网关的 MAC 地址,需进行 ARP 广播。
  4. 路由#
    1. 数据包到路由器后会先进行NAT网络地址转换,将源内网IP转为外网IP和指定端口号,目的MAC通过路由协议转为下一跳路由MAC, 源MAC和目的IP不变
    2. 通过动态路由协议转发到下一跳路由器,直到转发到目的IP对应路由器
    3. 此时会通过NAT将数据包 目的IP地址由外网ip地址转为内网ip地址,源MAC地址转为网关MAC地址,目的MAC由网关MAC转为目标服务器MAC地址,如不知道MAC地址需要进行ARP
    4. 此为一个包路由到目标机器的过程
  5. TCP三次握手#
    1. 你好,我是A; 你好A,我是B; 你好,B;
    2. img
    3. 握手过程存在封包与路由
  6. TLS 握手#
    1. 先非对称加密,然后对称加密,通过两边都知道的随机数和最后用服务端公钥加密的pre-master随机数,生成对称密钥,实现对称加密

    2. 数字证书是用CA私钥进行数字签名,此时如果本地的CA公钥和传过来的数字证书都是假的,是否能欺骗用户,不会,CA证书会由它的上级CA给它签名,确定它的身份,层层往上签名,一直到几个全球皆知的大CA root CA, 通过层层授信,确保传过来CA证书的正确性。同时保证了传过来的公钥的正确性

    3. img2

    4. 开始对称加密通信

三、服务端处理请求、客户端解析#

  1. http请求处理#
    1. 服务器拆分请求: 1.HTTP 请求方法 2.域名 3. 请求路径/页面
    2. 验证其上已经配置了 google.com 的虚拟主机
    3. 验证 google.com 接受 GET 方法
    4. 验证该用户可以使用 GET 方法
    5. 务器安装了 URL 重写模块,服务器会尝试匹配重写规则
    6. 根据请求信息获取相应的响应内容,这种情况下由于访问路径是 “/“ ,会访问首页文件, 可以重写这个规则
    7. 使用指定的处理程序分析处理这个文件,假如 Google 使用 PHP,服务器会使用 PHP 解析 index 文件,并捕获输出,把 PHP 的输出结果返回给请求者
  2. 浏览器客户端解析#
    1. 解析 —— HTML,CSS,JS
    2. 渲染 —— 构建 DOM 树 -> 渲染 -> 布局 -> 绘制

参考文献:

github: https://github.com/skyline75489/what-happens-when-zh_CN

趣谈网络协议: https://pan.baidu.com/s/1CK4a_lw_cYqpMPr186vEsQ 提取码: dydr

dns解析

参考文献:

https://www.zhihu.com/question/23042131/answer/66571369

https://segmentfault.com/a/1190000004127680

dns解析的过程可能是先递归再迭代,也可能是全部的递归。

本来的递归,说的是从客户端到本机的过程,一机一机的,就像层层方法调用再返回,泽旋说的应该是我图里的设置转发,本机转发到上一层,变成先递归到本机上一层,再迭代

默认都会转发,如果向上转发的过程中有,就返回,不支持,就开始迭代,支持但没有,就一直到根

只有一套,先递归再迭代,如果所有的dns服务器都设置了转发,就一直先向上转发到根,过程中可能就找到返回了,如果到根再往下找,如果过程中有dns服务器不支持转发,那这个服务器就开始迭代,直接从根往下,就相当于是先从客户端到这个不支持的dns服务器是递归。这个dns服务器的查找是迭代,如果一直都支持转发,就是全部的递归。

并发编程笔记-核心问题与BUG源头

并发编程核心问题

其实并发编程可以总结为三个核心问题:分工、同步、互斥。

所谓分工指的是如何高效地拆解任务并分配给线程,而同步指的是线程之间如何协作,互斥则是保证同一时刻只允许一个线程访问共享资源。Java SDK 并发包很大部分内容都是按照这三个维度组织的,例如 Fork/Join 框架就是一种分工模式,CountDownLatch 就是一种典型的同步方式,而可重入锁则是一种互斥手段。

流利阅读笔记

英语流利阅读 - 第一天单词笔记

reshape urban areas 重塑城市地区 urban 城市的

displacing 迫使…离开常居地

segments 部分,段

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×