diff --git "a/000 - 1 Computer Basics/01 \346\223\215\344\275\234\347\263\273\347\273\237.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/01 \346\223\215\344\275\234\347\263\273\347\273\237.md" similarity index 100% rename from "000 - 1 Computer Basics/01 \346\223\215\344\275\234\347\263\273\347\273\237.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/01 \346\223\215\344\275\234\347\263\273\347\273\237.md" diff --git "a/000 - 1 Computer Basics/02 \347\274\226\350\257\221\345\216\237\347\220\206.txt" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/02 \347\274\226\350\257\221\345\216\237\347\220\206.txt" similarity index 100% rename from "000 - 1 Computer Basics/02 \347\274\226\350\257\221\345\216\237\347\220\206.txt" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/02 \347\274\226\350\257\221\345\216\237\347\220\206.txt" diff --git "a/000 - 1 Computer Basics/03 \350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/03 \350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" similarity index 99% rename from "000 - 1 Computer Basics/03 \350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/03 \350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" index b37ef63b..bb6a0727 100644 --- "a/000 - 1 Computer Basics/03 \350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" +++ "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/03 \350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" @@ -1,486 +1,486 @@ - -## OSI(开放系统互联参考模型)标准模型 -**物理层** -负责为数据端设备透明地传输原始比特流,并且定义了数据终端设备和数据通信设备的物理和逻辑链接方法。传输单位是比特。 -协议:RJ45、CLOCK、IEEE802.3 -设备:(中继器,集线器) -**数据链路层** -将网络层传下来的IP数据报组装成帧,并检测和矫正物理层产生的传输差错,使得链路对网络层显示一条无差错、可靠的数据传输线路。功能可以概括为成帧,差错控制、流量控制和传输管理 -协议有:HDLC(高级数据链路控制协议),PPP,STP,SDLC,CSMA(载波监听多路访问) -设备:(网桥,交换机) -**网络层** -负载在网络层上将数据封装成数据报,将数据报从源端传到目的端,同时进行路由选择,为分组交换网上的不同主机提供通信服务。关键问题是对分组进行选择,并实现流量控制、拥塞控制、差错控制和网际互联等功能。传输单位数据报。 -协议: IP,ICMP(因特网控制报文协议),IGMP(因特网组管理协议),ARP,RARP,OSPF(开放最短路径优先),IPX -设备:路由器 -**传输层** -负责主机中两个进程之间的通信,为端到端连接提供可靠的传输服务。为端到端连接提供流量控制、差错控制、服务质量、数据传输管理等服务。 -协议:TCP,UDP -**会话层** -会话层允许不同主机上各个进程之间的**会话**,会话层利用传输层提供的端到端的服务,向表示层提供它的增值服务。这种服务主要是为表示层实体或用户进程**建立连接**并在连接上提供**有序**地传输数据。 -协议:SQL、RPC(远程调用协议) -**表示层** -用于处理两个通信系统中交换信息的表示方式。如数据压缩,加密和解密等。 -协议:JPEG、MPEG、ASII -**应用层** -是TCP/IP的最高层,它是直接为应用进程服务的一层。当不同的应用进程数据通信或数据交换时,就去调用应用层的**不同协议实体**,让这些实体去调用TCP或者UDP层服务来进行网络传输。 -协议:FTP(21) TELNET(23) SMTP(25) DNS(53) TFTP(69) HTTP(80) SNMP(161),DHCP(动态主机配置协议) - -## TCP/IP 分层 -1)**网络接口层(接收和发送数据报)** -负责将数据报发送到**网络介质**上,以及从网络上接收TCP/IP数据报,相当于OSI的物理层和数据层。 -2)**网际层(数据报封装和路由寻址功能)** -主要负责寻址和对数据报的封装以及重要的路由选择功能。 -3)**传输层** -**负责在应用进程之间的“端到端”的通信**,即从某个应用进程传输到另一个应用进程。 -4)应用层 -是TCP/IP的最高层,它是直接为应用进程服务的一层。当不同的应用进程数据通信或数据交换时,就去调用应用层的**不同协议实体**,让这些实体去调用TCP或者UDP层服务来进行网络传输。 - -## 五层体系结构模型 -物理层,数据链路层,网络层,传输层,应用层 - -## IP地址分类 -A类地址:以0开头, 第一个字节范围:1~126(1.0.0.0 - 126.255.255.255); -B类地址:以10开头, 第一个字节范围:128~191(128.0.0.0 - 191.255.255.255); -C类地址:以110开头, 第一个字节范围:192~223(192.0.0.0 - 223.255.255.255); -D类地址:1110开头, 224~239 -E类地址:11110开头, 240~255 -主机号全为0表示本网络本身 -主机号全为1表示本网络广播地址 -127.0.0.0 环路自检地址,表示任意主机本身 -32个0 表示本网络的本主机 -32个1表示整个TCP/IP网络的广播地址,等效本网络的广播地址。 -专用地址: -10.0.0.0—10.255.255.255, 172.16.0.0—172.31.255.255, 192.168.0.0—192.168.255.255。(Internet上保留地址用于内部) -IP地址与子网掩码相与得到网络号 - -## ARP是地址解析协议,简单语言解释一下工作原理 -每个主机都存有一个ARP高速缓存,存放本局域网上各主机和路由器的IP地址到MAC地址的映射表,称为ARP表。使用ARP协议动态维护此表。 -ARP工作在网络层中,其工作原理是:当主机A欲向本局域网上的某个主机B发送IP数据报时,就先在其ARP高速缓存中查看有无主机B的IP地址。如果有可以查出其对应的硬件地址,再将此硬件地址写入**MAC帧**,然后通过局域网将该MAC帧发往此硬件地址。如果没有,就通过使用目的MAC地址为本网络的广播地址即32个1的帧来封装并广播ARP请求分组,可以使同一个局域网里的所有主机收到ARP请求。当主机B收到该ARP请求后,就会向主机A发出响应ARP分组,分组中包含主机B的IP与MAC地址的映射关系,主机A在收到后将此映射写入ARP缓存中,然后按查询到的硬件地址发送MAC帧。 -**ARP是解决同一个局域网上主机与路由器的IP地址和硬件地址的映射问题**。如果所要找的主机和源主机不在同一个局域网上,那么通过ARP协议找到一个位于本局域网上的某个路由器硬件地址,然后把分组发送给这个路由器,让这个路由器把分组转发给下一个网络。 - -## 描述RARP协议 -RARP是逆地址解析协议,作用是完成硬件地址到IP地址的映射.(请求是广播,应答是单播) -1)网络上的每台设备都会有一个独一无二的硬件地址,通常是由设备厂商分配的MAC地址。主机从网卡上读取MAC地址,然后在网络上发送一个RARP请求的广播数据包,请求的RARP服务器分配一个IP地址。 -2)本地网段上的RARP服务器收到此请求后,检查其RARP列表,查找该MAC地址对应的IP地址。 -3)如果存在,RARP服务器就给源主机发送一个响应数据包并将此IP地址提供给对方主机使用。 -4)如果不存在,RARP服务器对此不做任何的响应。 -5)源主机收到从RARP服务器的响应信息,就利用得到的IP地址进行通讯;如果一直没有收到RARP服务器的响应信息,表示初始化失败 - - -## 了解交换机、路由器、网关的概念,并知道各自的用途 -两者简介: -**路由器**是具有多个输入输出端口的专用计算机,**其任务是连接不同的网络并完成路由转发**。当源主机向目标主机发送数据报时,路由器先检查源主机与目标主机是否连接在一个网络上。如果源主机和目标主机在一个网络上则直接交付而无需通过路由器。但如果源主机和目标主机不在同一个网络上,则路由器转发表指出路由将数据报转发给下一个路由器,即间接交付。路由器隔离了广播域。 - -**交换机**:是多个端口的网桥,工作在数据链路上,**将两个或多个以太网连接起来成为更大的以太网。它能将网络分成小的冲突域,为每个工作站提供更高的带宽**。其原理是,检测从以太端口来的数据帧的源和目的地的MAC地址,然后与系统内部的动态查找表进行比较。若数据帧的MAC地址不在查找表中,则将该地址加入查找表中,并将数据帧发送给相应的端口。 - -区别: -**路由器**:工作在网络层,是能够连接不同的广域网形成更大的广域网。连接的是异构网络。根据IP地址转发。 -**交换机**:工作在数据链路层,是将以太网连接形成更大的以太网,同一个网络。根据MAC地址进行转发。 - -**网关(Gateway)**又称网间连接器、协议转换器。网关在网络层以上实现网络互连,是最复杂的网络互连设备,**仅用于两个高层协议不同的网络互连**。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。 - -## OSI 和TCP/IP的区别 -1. OSI精确定义了服务、协议和接口,符合面向对象程序设计思想。而TCP/IP在这些概念上没有明确区分。 -2. OSI在产生协议之前没有偏向任何特定的协议,通用性良好,但设计没有太多经验不知道将哪些功能放到哪一层。TCP/IP,首先出现协议,模型实际上是对已有协议的描述。因此不会出现协议不能匹配的模式。 -3. TCP/IP考虑了异构网的互联问题,而OSI只考虑用一种标准的公用数据网将各种不同系统互连。 -4. OSI在网络层支持无连接和面向连接的通信,但在传输层仅有面向连接通信。而TCP/IP则相反,在网际层仅有无连接服务,在传输层支持无连接和面向连接两种模式。 - -## TCP与UDP的区别 -1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接 -2、TCP提供可靠全双功的通信服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP则是不可靠信道,尽最大努力交付,即不保证可靠交付 -3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的. -4.TCP具有拥塞控制,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等) -5、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信 -6、TCP首部开销20字节;UDP的首部开销小,只有8个字节. - -### TCP应用场景 -:效率要求相对低,但对准确性要求相对高的场景。因为传输中需要对数据确认、重发、排序等操作,相比之下效率没有UDP高。举几个例子:文件传输(准确高要求高、但是速度可以相对慢)、接受邮件、远程登录。 - -### UDP应用场景 -:效率要求相对高,对准确性要求相对低的场景。举几个例子:QQ聊天、在线视频、网络语音电话(即时通讯,速度要求高,但是出现偶尔断续不是太大问题,并且此处完全不可以使用重发机制)、广播通信(广播、多播)。 - -## TCP对应的协议和UDP对应的协议 -**TCP对应的协议**: -(1) FTP(21):定义了文件传输协议,使用21端口。常说某某计算机开了FTP服务便是启动了文件传输服务。下载文件,上传主页,都要用到FTP服务。 -(2) Telnet(23):(远程登陆协议)它是一种用于远程登陆的端口,用户可以以自己的身份远程连接到计算机上,通过这种端口可以提供一种基于DOS模式下的通信服务。如以前的BBS是-纯字符界面的,支持BBS的服务器将23端口打开,对外提供服务。 -(3) SMTP(25):定义了简单邮件传送协议,现在很多邮件服务器都用的是这个协议,用于发送邮件。如常见的免费邮件服务中用的就是这个邮件服务端口,所以在电子邮件设置-中常看到有这么SMTP端口设置这个栏,服务器开放的是25号端口。 -(4) POP3(110):它是和SMTP对应,POP3用于接收邮件。通常情况下,POP3协议所用的是110端口。也是说,只要你有相应的使用POP3协议的程序(例如Fo-xmail或Outlook),就可以不以Web方式登陆进邮箱界面,直接用邮件程序就可以收到邮件(如是163邮箱就没有必要先进入网易网站,再进入自己的邮-箱来收信)。 -(5)HTTP(80)协议:是从Web服务器传输超文本到本地浏览器的传送协议。 -**UDP对应的协议**: -(1) DNS(53):用于域名解析服务,将域名地址转换为IP地址。DNS用的是53号端口。 -(2) RIP:路由信息协议,端口520 -(2) SNMP(161):简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。 -(3) TFTP(69)(Trival File Transfer Protocal),简单文件传输协议,该协议在熟知端口69上使用UDP服务。 - -http://www.jianshu.com/p/8be9b3204864 -http://www.jianshu.com/p/eab86c0d1612 -## 常见的路由选择协议,以及它们的区别 -常见的路由选择协议有:RIP协议、OSPF协议。 -RIP协议(路由信息协议):底层是贝尔曼福特算法,**基于距离向量的路由选择协议**,它选择路由的度量标准(metric)是**跳数**,最大跳数是15跳,如果大于15跳,它就会丢弃数据包。仅和相邻路由器交换当前路由器所知道的全部信息。是应用层协议,使用UDP传输数据,端口520 -OSPF协议(开放最短路由优先):底层是迪杰斯特拉算法,**是链路状态路由选择协议**,它选择路由的度量标准是**带宽**,延迟。向本自治系统中所有路由器发送与本路由器相邻的所有路由器的链路状态,但这只是路由器知道的部分信息。网络层协议,直接IP数据报传输. - -## TCP报文首部 -源端口和目的端口,各占2个字节,分别写入源端口和目的端口; -序号,占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始; -确认号,占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701; -数据偏移,占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远; -保留,占6位,保留今后使用,但目前应都位0; -紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据; -**确认ACK**,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1; -推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1; -复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接; -**同步SYN**,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1; -**终止FIN**,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放; -窗口,占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受; -检验和,占2字节,校验首部和数据这两部分; -紧急指针,占2字节,指出本报文段中的紧急数据的字节数; -选项,长度可变,定义一些其他的可选的参数。 - -## TCP的三次握手与四次挥手过程,各个状态名称与含义,TIMEWAIT的作用 -**三次握手** -第一次握手:客户机首先向服务器的TCP发送一个连接请求报文段,这个特殊的报文段不含应用层数据,其首部中同步位 **SYN=1**。另外,客户机会随机选择一个起始序号 **seq=x**(连接请求报文不携带数据,但要消耗一个序号);客户端进程进入了 **SYN-SENT(同步已发送状态)状态** -第二次握手:服务器的TCP收到连接请求报文段后,如果同意建立连接,就向客户机发回确认,并为该TCP连接分配TCP缓存和变量。在确认报文段中,**SYN=1,ACK=1**,确认号字段值为 **ack=x+1**,并且服务器随机产生起始序号 **seq=y**. 确认包同样不包含应用层数据。 服务器进程进入了 **SYN-RCVD(同步收到)状态** -第三次握手:当客户机收到确认报文段后,还要向服务器给出确认,并且也要给该连接**分配缓存和变量**。这个报文段的确认为 **ACK=1**,序号段被设置为 **seq=x+1**,确认号字段 **ack=y+1**. 该报文段可以携带数据,如果不携带数据则不消耗序号。客户端进入 **ESTABLISHED(已建立连接)状态** -理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。因为TCP提供全双工通信,因此双方任何时候都可以发送数据。 - -### 为什么TCP客户端最后还要发送一次确认呢? - 一句话,主要 **防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误**。 - - 如果使用的是两次握手建立连接,假设有这样一种场景,**客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文**,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。 - - 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。 - -**四次挥手** -第一次挥手:客户机打算关闭连接,就向其TCP发送一个连接释放报文,并停止再发送数据,主动关闭TCP连接。该报文段的 **FIN=1**,**seq=u**,它等于前面已经发送过的数据的最后一个字节的序号加1。 客户端进入 **FIN-WAIT-1(终止等待1)状态** -第二次挥手:服务器收到连接释放报文段后即发出确认,确认号是ack=u+1,序号为v,等于它前面已经发送过的数据的最后一个字节序号加1.此时客户机到服务器这个方向的连接就释放了,TCP处于半关闭状态。**ACK=1,seq=v,ack=u+1**,服务端就进入了 **CLOSE-WAIT(关闭等待)状态** -客户端收到第二次挥手 ,客户端进入 **FIN-WAIT-2(终止等待2)状态** -第三次挥手:若服务器已经没有要向客户机发送的数据,就通知TCP释放连接,此时发出 **FIN=1**,确认号 **ack= u+1** ,序号 **seq =w**,已经发送过的数据最后一个字节加1。确认为ACK=1. 服务器就进入了 **LAST-ACK(最后确认)状态** -(**FIN = 1, ACK=1,seq = w, ack =u+1**) -第四次挥手:客户机收到连接释放报文段后,必须发出确认。在确认报文段中,确认位 **ACK=1**,序号 **seq=u+1**,确认号 **ack=w+1** . 此时连接还没有释放掉,**必须经过实践等待计时器设置的时间2MSL(Max Segment Lifetime),后**,客户机才进入连接关闭状态。 -(**ACK=1,seq=u+1,ack=w+1**) - -### 为什么客户端最后还要等待2MSL? - MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。 - - 第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,**站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,** 而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。 - - 第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。 - -### 为什么建立连接是三次握手,关闭连接确是四次挥手呢? - - 建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 - 而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而 **自己也未必全部数据都发送给对方了**,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。 - -### 如果已经建立了连接,但是客户端突然出现故障了怎么办? - TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。 - -https://blog.csdn.net/qzcsu/article/details/72861891 -http://www.cnblogs.com/Jessy/p/3535612.html - -## 为什么会采用三次握手,若采用二次握手可以吗? -采用三次握手是为了防止失效的连接请求报文段再次传到服务器,因而产生错误。如果由于网络不稳定,虽然客户端以前发送的连接请求以到达服务方,但服务方的同意连接的应答未能到达客户端。则客户方要重新发送连接请求,若采用二次握手,服务方收到客服端重传的请求连接后,会以为是新的请求,就会发送同意连接报文,并新开进程提供服务,这样会造成服务方资源的无谓浪费。 -如果只采用一次的话,客户端不知道服务端是否已经收到自己发送的数据,则会不断地发送数据。为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手 - - -## 为什么四次挥手,主动方要等待2MSL后才关闭连接. -一、保证TCP协议的全双工连接能够可靠关闭. -主要为了确保对方能受到ACK信息. 如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。所以,Client不是直接进入CLOSED,而是要保持2MSL,如果在这个时间内又收到了server的关闭请求时可以进行重传,否则说明server已经受到确认包则可以关闭. - - -https://www.zhihu.com/question/36930631 -## TCP拥塞控制 -为了更好对TCP进行拥塞控制,因特网建议标准定义了以下四种算法:慢开始,拥塞避免,快重传,快恢复。 -首先在TCP要求发送端维护两个窗口: -1) 接收窗口rwnd,接收方根据当前缓存大小锁许诺的最新窗口值。 -2) 拥塞窗口 cwnd ,发送方根据自己估算的网络拥塞程度而设置的窗口值。 -发送窗口的上限是取这两者的最小值。 -慢开始: TCP刚连接好时,先令拥塞窗口cwnd =1 ,在每次收到一个对新报文段的确认时将cwnd加1. Cwnd的大小呈指数增长。 -拥塞避免算法: 当cwnd大于等于慢开始门限ssthresh时,cwnd窗口每次加1而不是加倍。当发送方检测到**超时事件**的发生时,就将慢开始门限设置为当前cwnd的一半,同时将cwnd设置为1. 这样的目的是迅速减少主机发送到网络的分组数,使得发生拥塞的路由器有足够的时间吧队列中积压的分组处理完毕。 -快重传:当发送方连续收到三个重复的ACK报文时,直接重传对方尚未收到的报文段,而不必等待那个报文段设置的重传计时器超时。 -快恢复:当发送端收到连续三个冗余的ACK时,就执行“乘法减小”算法,把慢开始门限ssthresh减半,cwnd设置为慢开始门限减半后的数值(与慢开始不同)。 - -## TCP滑动窗口与回退N针协议 -滑动窗口: -发送方都维持一组连续的允许发送的帧的序号称为发送窗口。同时接收方也维持一组连续的允许接收的帧序号,称为接收窗口。发送窗口是用来对发送方进行流量控制,接收窗口是用来控制接收那些数据帧不可以接收那些帧。 -在发送端,收到一个确认帧,发送窗口就向前滑动一个帧位置,当发送窗口没有可以发送的帧时,发送方就停止发送。直到接收方发送的确认帧使发送窗口向前移动。 -在接收端,只有收到数据帧的序号落在接收窗口内才将该帧收下,否则一律丢弃。每收到一个帧后就发送回确认帧。 - -后退N帧协议 -发送窗口大于1,接收窗口等于1.在后退N帧中,发送方不需要收到上一帧的ACK后才能发送下一帧,而是可以连续发送帧。当接收方检测出失序信息帧后,要求发送方重发最后一个正确接收的帧之后的所有未被确认的帧。源站每发完一帧就要为该帧设置超时计时器,如果在超时时间内没有收到确认帧则进行重发。服务端会采用累积确认的方式,不是每个帧都发确认,可以连续收到好几个正确帧后发回一个确认信息。接收方因为窗口为1,所以必须按序接收数据帧,如果某个序大于当前所期望的序号时就会连续发送3个ACK确认帧,要求客户端重传失序帧。 - -## TCP的可靠性如何保证 -在TCP的连接中,数据流必须以正确的顺序送达对方。TCP的可靠性是通过顺序编号和确认(ACK)来实现的。TCP在开始传送一个段时,为准备重传而首先将该段插入到发送队列之中,同时启动时钟。其后,如果收到了接受端对该段的ACK信息,就将该段从队列中删去。如果在时钟规定的时间内,ACK未返回,那么就从发送队列中再次送出这个段。TCP在协议中就对数据可靠传输做了保障,握手与断开都需要通讯双方确认,数据传输也需要双方确认成功,在协议中还规定了:分包、重组、重传等规则;而UDP主要是面向不可靠连接的,不能保证数据正确到达目的地。 - -## Http的报文结构 -http请求由三部分组成,分别是:请求行、消息报头、请求正文 -方法 [空格] URL [空格] 版本 -首部字段名: [空格] 值 -… -首部字段名: [空格] 值 -[空一行] -实体主体 - -HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文 -版本[空格] 状态码 [空格] 短语 -首部字段名: [空格] 值 -… -首部字段名: [空格] 值 -[空一行] -实体主体 -更多http内容参考:http://www.cnblogs.com/maanshancss/p/4503385.html - -## Http request的几种类型 -HTTP协议中共定义了八种方法或者叫“动作”来表明对Request-URI指定的资源的不同操作方式,具体介绍如下: -GET:向特定的资源发出请求。 -POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。 -PUT:向指定资源位置上传其最新内容。 -DELETE:请求服务器删除Request-URI所标识的资源。 -HEAD:请求读取由URL所标志的信息的首部。 -OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送' * '的请求来测试服务器的功能性。 -TRACE:回显服务器收到的请求,主要用于测试或诊断。 -CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 - -## Http1.1和Http1.0的区别 -1)HTTP1.0 是短连接,HTTP1.1是长连接。 HTTP 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求。如果一个html包含多个图片或资源时需要多次与服务器建立连接。 HTTP 1.1支持持久连接,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接.HTTP 1.1采用了流水线的持久连接,即客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。 -2)HTTP 1.0不支持Host请求头字段,WEB浏览器无法使用主机头名来明确表示要访问服务器上的哪个WEB站点,这样就无法使用WEB服务器在同一个IP地址和端口号上配置多个虚拟WEB站点。在HTTP 1.1中增加Host请求头字段后,WEB浏览器可以使用主机头名来明确表示要访问服务器上的哪个WEB站点,这才实现了在一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点。 -3)HTTP 1.1还提供了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头 -4)带宽优化。HTTP/1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了。例如,客户端只需要显示一个文档的部分内容,又比如下载大文件时需要支持断点续传功能,而不是在发生断连后不得不重新下载完整的包。 -HTTP/1.1中在请求消息中引入了range头域,它允许只请求资源的某个部分。 -5) HTTP/1.1增加了OPTIONS方法,它允许客户端获取一个服务器支持的方法列表 - -http://blog.csdn.net/forgotaboutgirl/article/details/6936982 - -## Http怎么处理长连接 -HTTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持久连接支持。TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了带宽。 -使用长连接的HTTP协议,会在响应头有加入这行代码:Connection:keep-alive 。在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。 - -http://www.codeceo.com/article/http-long-connect.html - -## Cookie与Session的作用于原理 -会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。 -Cookie -Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就产生一个用户身份标识,然后在响应消息中将该标识号以Cookie的形式传递给浏览器.客户端浏览器会把Cookie保存起来。浏览器在以后每次访问该web服务器时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容. Cookie不能被浏览器共享 -Cookie具有不可跨域名性,例如浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Cookie的maxAge决定着Cookie的有效期,单位为秒(Second) -**默认情况下,cookie是一个会话级别的,用户退出浏览器后被删除** - -Session -Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。 -如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。 -Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。 - -session工作原理 -(1)web不会在客户端开始访问它时创建session,在访问特殊的程序并且该程序(servlet)决定与客户端开启会话时,服务器生成一个唯一值,称为Session ID(好像是通过取进程ID的方式取得的)。服务器开辟一块内存,对应于该Session ID。 -(2)服务器再将该Session ID写入浏览器的cookie。 -(3)服务器内有一进程,监视所有Session的活动状况,如果有Session超时或是主动关闭,服务器就释放改内存块。 -(4)当浏览器连入服务器时并请求Session时,服务器就读浏览器Cookie中的Session ID。 -(5)然后,服务检查该Session ID所对应的内存是否有效。 -(6)如果有效,就读出内存中的值。 -(7)如果无效,就建立新的Session。 - -**tomcat默认设置是30分钟** -具体设置很简单,方法有三种: -(1)在主页面或者公共页面中加入:session.setMaxInactiveInterval(900); -参数900单位是秒,即在没有活动15分钟后,session将失效。设置为-1将永不关闭。 -这里要注意这个session设置的时间是根据服务器来计算的,而不是客户端。所以如果是在调试程序,应该是修改服务器端时间来测试,而不是客户端。 -(2)也是比较通用的设置session失效时间的方法,就是在项目的web.xml中设置 - -15 - -这里的15也就是15分钟失效. -(3)直接在应用服务器中设置,如果是tomcat,可以在tomcat目录下conf/web.xml中 -找到元素,tomcat默认设置是30分钟,只要修改这个值就可以了。 -需要注意的是如果上述三个地方如果都设置了,有个优先级的问题,从高到低: -(1)-->(2)--->(3) - -生命周期: -1)tomcat默认是30分钟 -2)因为session和cookie有关系,客户端浏览器通过cookie维持该会话,cookie不支持跨浏览器共享,意味着如果把浏览器关该会闭的话该会话就会失效(但服务端还保存着)。因此同一机器的两个浏览器窗口访问服务器时,会生成两个不同的Session。 - -http://qiusuoge.com/10576.html -http://blog.csdn.net/colzer/article/details/8686966 -http://www.cnblogs.com/binger/archive/2013/03/19/2970171.html - -## 电脑上访问一个网页,整个过程是怎么样的:DNS、HTTP、TCP、OSPF、IP、ARP -1) 浏览器分析连接指向的页面URL(http://www.baidu.com) -2) 浏览器向DNS请求www.baidu.com.的IP地址 -3) 域名系统DNS解析出百度官网的服务器IP地址 -4) 浏览器与该服务器建立TCP连接(默认端口80) -5) 浏览器发出HTTP请求获取指定页面。 -6) 服务器通过HTTP响应把文件对应页面发送给浏览器。 -7) TCP连接释放。 -8) 浏览器将文件进行解析,并将web网页显示给用户。 - -## get提交和post提交的区别 -1.根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的。 -  (1).所谓安全的意味着该操作用于获取信息而非修改信息。换句话说,GET 请求一般不应产生副作用。就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。 -  (2).幂等的意味着对同一URL的多个请求应该返回同样的结果。 -2.根据HTTP规范,POST表示可能修改变服务器上的资源的请求。还是新闻以网站为例,读者对新闻发表自己的评论应该通过POST实现,因为在评论提交后站点的资源已经不同了,或者说资源被修改了。 -3.GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连.POST把提交的数据则放置在是HTTP包的包体中。 -4.GET安全性较低,POST安全性较高。因为GET在传输过程,数据被放在请求的URL中,而如今现有的很多服务器、代理服务器或者用户代理都会将请求URL记录到日志文件中,然后放在某个地方,这样就可能会有一些隐私的信息被第三方看到。另外,用户也可以在浏览器上直接看到提交的数据,一些系统内部消息将会一同显示在用户面前。 -5.get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。 -6.在FORM(表单)中,Method默认为"GET" - - -幂等(idempotent、idempotence)是一个数学或计算机学概念,常见于抽象代数中。 -  幂等有一下几种定义: -  对于单目运算,如果一个运算对于在范围内的所有的一个数多次进行该运算所得的结果和进行一次该运算所得的结果是一样的,那么我们就称该运算是幂等的。比如绝对值运算就是一个例子,在实数集中,有abs(a)=abs(abs(a))。 -  对于双目运算,则要求当参与运算的两个值是等值的情况下,如果满足运算结果与参与运算的两个值相等,则称该运算幂等,如求两个数的最大值的函数,有在在实数集中幂等,即max(x,x) = x。 -详见: http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html -http://www.cnblogs.com/skynet/archive/2010/05/18/1738301.html - -## https如何加密的 -HTTPS介绍: -HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议 它是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息。**它使用安全套接字层(SSL)进行信息交换**,简单来说它是HTTP的安全版。 它是由Netscape开发并内置于其浏览器中,使用SSL在发送方把原始数据进行加密,然后在接受方进行解密保证数据的安全性.然而,加密和解密过程需要耗费系统大量的开销,严重降低机器的性能. -HTTPS实际上就是SSL over HTTP,它使用默认端口**443**,而不是像HTTP那样使用端口80来和TCP/IP进行通信。HTTPS协议使用SSL在发送方把原始数据进行加密,然 后在接受方进行解密,加密和解密需要发送方和接受方通过交换共知的密钥来实现,因此,所传送的数据不容易被网络黑客截获和解密.然而,加密和解密过程需要耗费系统大量的开销,严重降低机器的性能,相关测试数据表明使用HTTPS协议传输数据的工作效率只有使用HTTP协议传输的十分之一。 - -如何实现加密:(其实就是sssl的交互过程) -HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。具体是如何进行加密,解密,验证的 - -http://blog.csdn.net/binyao02123202/article/details/8049446 -http://www.codeceo.com/article/why-http-better-than-https.html - -## http和https的区别 -1. https协议需要到ca申请证书,一般免费证书很少,需要交费。 -2. http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议 http和https使用的是完全不同的连接方式用的端口也不一样:前者是80,后者是443。 -3. http的连接很简单,是无状态的 HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全 HTTPS解决的问题. -http://www.admin5.com/article/20150708/608526.shtml - -## SSL协议及完整交互过程 -SSL是Netscape公司所提出的安全保密协议,在浏览器(如Internet Explorer、Netscape Navigator)和Web服务器(如Netscape的Netscape Enterprise Server、ColdFusion Server等等)之间构造安全通道来进行数据传输,SSL运行在TCP/IP层之上、应用层之下,为应用程序提供加密数据通道,它采用了RC4、MD5 以及RSA等加密算法,使用40 位的密钥,适用于商业信息的加密。 - -开始加密通信之前,客户端和服务器首先必须建立连接和交换参数,这个过程叫做握手(handshake)。 -**1 客户端发出请求(ClientHello)** -首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做ClientHello请求。在这一步,客户端主要向服务器提供以下信息。 -(1) 支持的协议版本,比如TLS 1.0版。 -(2) 一个客户端生成的随机数,稍后用于生成"对话密钥"。 -(3) 支持的加密方法,比如RSA公钥加密。 -(4) 支持的压缩方法。 - -**4.2 服务器回应(SeverHello)** -服务器收到客户端请求后,向客户端发出回应,这叫做SeverHello。服务器的回应包含以下内容: -(1) 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。 -(2) 一个服务器生成的随机数,稍后用于生成"对话密钥"。 -(3) 确认使用的加密方法,比如RSA公钥加密。 -(4) 服务器证书。(公钥) -**4.3 客户端回应** -客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。 -如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息。 -(1) 一个随机数。该随机数用服务器公钥加密,防止被窃听。 -(2) 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。 -(3) 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。 -上面第一项的随机数,是整个握手阶段出现的第三个随机数,又称"pre-master key"。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。(会话秘钥是采用对称加密方式,而这里的公钥是采用非对称加密) -**4 服务器的最后回应** -服务器通过私钥解密收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的"会话密钥"。然后,向客户端最后发送下面信息。 -(1)编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。 -(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。 -至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容。 - -至于为什么一定要用三个随机数,来生成"会话密钥",dog250解释得很好: -"不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。 -对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。 -pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。" - -http://limboy.me/tech/2011/02/19/https-workflow.html -http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html -http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html -http://kb.cnblogs.com/page/162080/ - -## https处理的一个过程,对称加密和非对称加密(参考上一条,这一条就是通俗的表示) -1. SSL原理很简单。当你的浏览器向服务器请求一个安全的网页(通常是 https://) -2. 服务器就把它的证书和公匙发回来 -3. 浏览器检查证书是不是由可以信赖的机构颁发的,确认证书有效和此证书是此网站的。 -4. 浏览器使用公钥加密了一个随机对称密钥,包括加密的URL一起发送到服务器。 -5. 服务器用自己的私匙解密了你发送的钥匙。然后用这把对称加密的钥匙给你请求的URL链接解密。 -6. 服务器用你发的对称钥匙给你请求的网页加密。你也有相同的钥匙就可以解密发回来的网页了 - -加密算法绝大部分都属于以下两种加密类型之一: -对称加密:加密解密用的是同样的“钥匙” -非对称加密:加密解密用的是不同的“钥匙” - -对称加密 -Alice 在盒子里放有信息,盒子上有挂锁,她有钥匙。通过邮局她把这个盒子寄给Bob。Bob收到盒子后,用相同的钥匙打开盒子(钥匙之前就得到了,可能是Alice面对面给他的)。然后Bob可以用同样的方法回复。 - -非对称加密 -Bob和Alice各有自己的盒子。Alice要跟Bob秘密通信,她先让Bob把开着的盒子通过邮局发给她。Alice拿到盒子后放入信息锁上,然后发给Bob。Bob就可以用他自己的钥匙打开了。回复的话就用同样的方法。 -非对称算法在加密和解密时用的是不同的钥匙。信息接受者有两把钥匙:一把“公匙”,一把“私匙”。公匙是给信息发送者用来加密的,私匙是自己用来解密的。这样最大的好处是:不必通过不安全的渠道发送私密的东西。公匙本来就是给别人用的,不用藏好。你的私匙在你产生私匙的电脑里保存着。 - -http://article.yeeyan.org/view/90729/174903/ - -## Http和https的区别 - - http是HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份 - - https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对 - - 加密,但对称加密的密钥用服务器方的证书进行了非对称加密。此外客户端可以验证服务器端的身份 - - 如果配置了客户端验证,服务器方也可以验证客户端的身份。 - - https协议需要到ca申请证书,一般免费证书很少,需要交费。 - - http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议 - - http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。 - - http的连接很简单,是无状态的 - - HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全 - -https://github.com/Wl201314/MartinBlog/tree/master/Blog/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80 -## DNS域名系统,简单描述其工作原理。 -域名系统DNS是因特网使用的命名系统,用于把便于人们记忆的含有特定含义的主机名转换为便于机器处理的IP地址。DNS系统采用C/S模式,其协议运行在UDP上,使用53号端口。从概念上讲DNS可以分为3个部分:层次域名空间,域名服务器和解析器。 - -域名解析是把域名映射成IP地址或者把IP地址映射成域名的过程。域名解析有两种方式:递归查询和迭代查询。 -递归查询:如果本地主机询问的本地域名服务器不知道被查询的域名IP地址,那么**本地域名服务器**就以DNS客户的身份,向**根域名服务器**继续发出查询请求报文,而不是自己进行下一步非查询。根域名服务器会继续向**顶级域名服务器**查询请求,如果存在则直接返回给根服务器,否则顶级域名服务器向对应的**权限域名服务器**查询。是一种递归的查询方式。 - -迭代查询:如果本地主机询问的本地域名服务器不知道被查询的域名IP地址,那么本地域名服务器就以DNS客户的身份,向根域名服务器继续发出查询请求报文。跟服务器收到请求报文时,要么给出所有查询的IP地址,要么告诉本地域名服务器下一步需要查询的顶级域名服务器。然后本地服务器向这个顶级域名服务器进行后续的查询。同样的顶级域名服务器收到查询报文后,要么给出所要查询的IP地址,要么告诉本地域名服务器下一步应该查找那个权限域名服务器。 - -## 面向连接和非面向连接的服务的特点是什么? -面向连接的服务:通信双方进行通信之前,必须先建立连接,在通信过程中,整个连接情况一直都是被实时地监控和管理。当通信结束后,则应释放这个连接。 -无连接服务:两个实体之间的通信不需要先建立好连接,需要通信的时候,直接将信息发送到”网络”中,让该信息的传递在网上尽力而为地往目的地传送。 - -## 端口及对应的服务? -FTP 21 SSH 22 telnet 23 SMTP 25 Domain(域名服务器) 53 HTTP 80 -POP3 110 NTP(网络时间协议)123 MySQL数据库服务3306 https 443 SNMP(161) TFTP(69) -Shell或 cmd 514 POP-2 109 SQL Server 1433 - -## 各种协议 -ICMP协议: 因特网控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。 -TFTP协议: 是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。 -HTTP协议: 超文本传输协议,是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。 -DHCP协议: 动态主机配置协议,是一种让系统得以连接到网络上,并获取所需要的配置参数手段。 -NAT协议:网络地址转换属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术, -DHCP协议:一个局域网的网络协议,使用UDP协议工作,用途:给内部网络或网络服务供应商自动分配IP地址,给用户或者内部网络管理员作为对所有计算机作中央管理的手段。 - -## Ping的整个过程 -同一个局域网中: -1、Pc1在应用层发起个目标IP位IP2的Ping请求。 -2、传输层接到上层请求的数据,将数据分段并加上UDP报头。下传到Internet层。 -3、 网际层接收来处上层的数据后,根据ICMP协议进行封装,添加PC1的IP为源IP为和PC2IP为目标IP后封装成数据包。下传到网络接口层。 -4、网络接口层接收数据包后,进行封装,源MAC地址为PC1的MAC地址,目标MAC地址则查询自己的ARP缓存表获取。如果PC1 arp缓存表中没有目标IP对应的MAC地址,则PC1发出一个ARP广播报文。ARP报文中源MAC地址为Pc1mac地址,源IP地址为pc1 IP,所要请求的是PC2的IP对应的mac地址。 -5、PC2收到ARP广播后,进行解封装,发现所请求的MAC地址是自己的。则PC2将PC1的mac地址写入arp缓存表中。然后向PC1发送一个 ARP应答单播。该单播消息包括目标IP为PC1ip,目标Mac为pc1mac地址,源IP为PC2的IP,源Mac为pc2的Mac。 -6、Pc1接收到PC2的arp应答报文后,将Pc2的MAC地址存入arp缓存中,并将Pc2的Mac地址作为目标地址封装到数据帧中。发给下层进行网络传输。 -7、PC2接收这个帧后,在网络接口层查看目标mac地址是否指向自己。是,PC2则将帧头去掉,向上层传输。 -8、Pc2网际层接收到这个信息包,查看包头,发现目标IP和自己匹配,则解封装,将数据向上层传输。 -9、传输层接收来自下层的Ping请求的UDP报文,则去掉UDP报头,向应用层传送。 -10、应用层收到ping请求后,发送一个PIng回应报文给PC1 -http://blog.chinaunix.net/uid-26758209-id-3146224.html - -## ICMP协议: -1) ICMP允许主机或路由报告差错情况和提供有关异常情况。ICMP是因特网的标准协议,但ICMP不是高层协议,而是IP层的协议。通常ICMP报文被IP层或更高层协议(TCP或UDP)使用。一些ICMP报文把差错报文返回给用户进程。 -2) ICMP报文作为IP层数据报的数据,加上数据报的首部,组成数据报发送出去。 -3) ICMP报文的种类有两种,即ICMP差错报告报文和ICMP询问报文。 - -差错报告 -ICMP差错报告报文共有5种: - 终点不可达:终点不可达分为:网络不可达,主机不可达,协议不可达,端口不可达,需要分片但DF比特已置为1,以及源路由失败等六种情况,其代码字段分别置为0至5。当出现以上六种情况时就向源站发送终点不可达报文。 -说明: -端口不可达:UDP的规则之一是:如果收到UDP数据报而且目的端口与某个正在使用的进程不相符,那么UDP返回一个ICMP不可达报文。 -源站抑制:当路由器或主机由于拥塞而丢弃数据报时,就向源站发送源站抑制报文,使源站知道应当将数据报的发送速率放慢。 -时间超过:当路由器收到生存时间为零的数据报时,除丢弃该数据报外,还要向源站发送时间超过报文。当目的站在预先规定的时间内不能收到一个数据报的全部数据报片时,就将已收到的数据报片都丢弃,并向源站发送时间超过报文。 -参数问题:当路由器或目的主机收到的数据报的首部中的字段的值不正确时,就丢弃该数据报,并向源站发送参数问题报文。 -改变路由(重定向)路由器将改变路由报文发送给主机,让主机知道下次应将数据报发送给另外的路由器。 - -询问报文 -ICMP询问报文有四种 -**回送请求和回答**,ICMP回送请求报文是由主机或路由器向一个特定的目的主机发出的询问。收到此报文的机器必须给源主机发送ICMP回送应答报文。这种询问报文用来测试目的站是否可达以及了解其有关状态 -**时间戳请求和回答**:ICMP时间戳请求允许系统向另一个系统查询当前的时间。该ICMP报文的好处是它提供了毫秒级的分辨率,而利用其他方法从别的主机获取的时间只能提供秒级的分辨率。请求端填写发起时间,然后发送报文。应答系统收到请求报文时填写接收时间戳,在发送应答时填写发送时间戳。大多数的实现是把后面两个字段都设成相同的值。 -**掩码地址请求和回答**:主机使用ICMP地址掩码请求报文可向子网掩码服务器得到某个接口的地址掩码。 -**路由器询问和通过**:主机使用ICMP路由器询问和通过报文可了解连接在本网络上的路由器是否正常工作。主机将路由器询问报文进行广播(或多播)。收到询问报文的一个或几个路由器就使用路由器通过报文广播其路由选择信息 - -## C/S模式下使用socket通信,几个关键函数 - -## 知识点: -1) SSP通过七号信令网实现与SAU的连接,而SCP与SAU之间通过TCP/IP协议连接。 -2) 重组发生在目的主机,分片发生在路由器上 + +## OSI(开放系统互联参考模型)标准模型 +**物理层** +负责为数据端设备透明地传输原始比特流,并且定义了数据终端设备和数据通信设备的物理和逻辑链接方法。传输单位是比特。 +协议:RJ45、CLOCK、IEEE802.3 +设备:(中继器,集线器) +**数据链路层** +将网络层传下来的IP数据报组装成帧,并检测和矫正物理层产生的传输差错,使得链路对网络层显示一条无差错、可靠的数据传输线路。功能可以概括为成帧,差错控制、流量控制和传输管理 +协议有:HDLC(高级数据链路控制协议),PPP,STP,SDLC,CSMA(载波监听多路访问) +设备:(网桥,交换机) +**网络层** +负载在网络层上将数据封装成数据报,将数据报从源端传到目的端,同时进行路由选择,为分组交换网上的不同主机提供通信服务。关键问题是对分组进行选择,并实现流量控制、拥塞控制、差错控制和网际互联等功能。传输单位数据报。 +协议: IP,ICMP(因特网控制报文协议),IGMP(因特网组管理协议),ARP,RARP,OSPF(开放最短路径优先),IPX +设备:路由器 +**传输层** +负责主机中两个进程之间的通信,为端到端连接提供可靠的传输服务。为端到端连接提供流量控制、差错控制、服务质量、数据传输管理等服务。 +协议:TCP,UDP +**会话层** +会话层允许不同主机上各个进程之间的**会话**,会话层利用传输层提供的端到端的服务,向表示层提供它的增值服务。这种服务主要是为表示层实体或用户进程**建立连接**并在连接上提供**有序**地传输数据。 +协议:SQL、RPC(远程调用协议) +**表示层** +用于处理两个通信系统中交换信息的表示方式。如数据压缩,加密和解密等。 +协议:JPEG、MPEG、ASII +**应用层** +是TCP/IP的最高层,它是直接为应用进程服务的一层。当不同的应用进程数据通信或数据交换时,就去调用应用层的**不同协议实体**,让这些实体去调用TCP或者UDP层服务来进行网络传输。 +协议:FTP(21) TELNET(23) SMTP(25) DNS(53) TFTP(69) HTTP(80) SNMP(161),DHCP(动态主机配置协议) + +## TCP/IP 分层 +1)**网络接口层(接收和发送数据报)** +负责将数据报发送到**网络介质**上,以及从网络上接收TCP/IP数据报,相当于OSI的物理层和数据层。 +2)**网际层(数据报封装和路由寻址功能)** +主要负责寻址和对数据报的封装以及重要的路由选择功能。 +3)**传输层** +**负责在应用进程之间的“端到端”的通信**,即从某个应用进程传输到另一个应用进程。 +4)应用层 +是TCP/IP的最高层,它是直接为应用进程服务的一层。当不同的应用进程数据通信或数据交换时,就去调用应用层的**不同协议实体**,让这些实体去调用TCP或者UDP层服务来进行网络传输。 + +## 五层体系结构模型 +物理层,数据链路层,网络层,传输层,应用层 + +## IP地址分类 +A类地址:以0开头, 第一个字节范围:1~126(1.0.0.0 - 126.255.255.255); +B类地址:以10开头, 第一个字节范围:128~191(128.0.0.0 - 191.255.255.255); +C类地址:以110开头, 第一个字节范围:192~223(192.0.0.0 - 223.255.255.255); +D类地址:1110开头, 224~239 +E类地址:11110开头, 240~255 +主机号全为0表示本网络本身 +主机号全为1表示本网络广播地址 +127.0.0.0 环路自检地址,表示任意主机本身 +32个0 表示本网络的本主机 +32个1表示整个TCP/IP网络的广播地址,等效本网络的广播地址。 +专用地址: +10.0.0.0—10.255.255.255, 172.16.0.0—172.31.255.255, 192.168.0.0—192.168.255.255。(Internet上保留地址用于内部) +IP地址与子网掩码相与得到网络号 + +## ARP是地址解析协议,简单语言解释一下工作原理 +每个主机都存有一个ARP高速缓存,存放本局域网上各主机和路由器的IP地址到MAC地址的映射表,称为ARP表。使用ARP协议动态维护此表。 +ARP工作在网络层中,其工作原理是:当主机A欲向本局域网上的某个主机B发送IP数据报时,就先在其ARP高速缓存中查看有无主机B的IP地址。如果有可以查出其对应的硬件地址,再将此硬件地址写入**MAC帧**,然后通过局域网将该MAC帧发往此硬件地址。如果没有,就通过使用目的MAC地址为本网络的广播地址即32个1的帧来封装并广播ARP请求分组,可以使同一个局域网里的所有主机收到ARP请求。当主机B收到该ARP请求后,就会向主机A发出响应ARP分组,分组中包含主机B的IP与MAC地址的映射关系,主机A在收到后将此映射写入ARP缓存中,然后按查询到的硬件地址发送MAC帧。 +**ARP是解决同一个局域网上主机与路由器的IP地址和硬件地址的映射问题**。如果所要找的主机和源主机不在同一个局域网上,那么通过ARP协议找到一个位于本局域网上的某个路由器硬件地址,然后把分组发送给这个路由器,让这个路由器把分组转发给下一个网络。 + +## 描述RARP协议 +RARP是逆地址解析协议,作用是完成硬件地址到IP地址的映射.(请求是广播,应答是单播) +1)网络上的每台设备都会有一个独一无二的硬件地址,通常是由设备厂商分配的MAC地址。主机从网卡上读取MAC地址,然后在网络上发送一个RARP请求的广播数据包,请求的RARP服务器分配一个IP地址。 +2)本地网段上的RARP服务器收到此请求后,检查其RARP列表,查找该MAC地址对应的IP地址。 +3)如果存在,RARP服务器就给源主机发送一个响应数据包并将此IP地址提供给对方主机使用。 +4)如果不存在,RARP服务器对此不做任何的响应。 +5)源主机收到从RARP服务器的响应信息,就利用得到的IP地址进行通讯;如果一直没有收到RARP服务器的响应信息,表示初始化失败 + + +## 了解交换机、路由器、网关的概念,并知道各自的用途 +两者简介: +**路由器**是具有多个输入输出端口的专用计算机,**其任务是连接不同的网络并完成路由转发**。当源主机向目标主机发送数据报时,路由器先检查源主机与目标主机是否连接在一个网络上。如果源主机和目标主机在一个网络上则直接交付而无需通过路由器。但如果源主机和目标主机不在同一个网络上,则路由器转发表指出路由将数据报转发给下一个路由器,即间接交付。路由器隔离了广播域。 + +**交换机**:是多个端口的网桥,工作在数据链路上,**将两个或多个以太网连接起来成为更大的以太网。它能将网络分成小的冲突域,为每个工作站提供更高的带宽**。其原理是,检测从以太端口来的数据帧的源和目的地的MAC地址,然后与系统内部的动态查找表进行比较。若数据帧的MAC地址不在查找表中,则将该地址加入查找表中,并将数据帧发送给相应的端口。 + +区别: +**路由器**:工作在网络层,是能够连接不同的广域网形成更大的广域网。连接的是异构网络。根据IP地址转发。 +**交换机**:工作在数据链路层,是将以太网连接形成更大的以太网,同一个网络。根据MAC地址进行转发。 + +**网关(Gateway)**又称网间连接器、协议转换器。网关在网络层以上实现网络互连,是最复杂的网络互连设备,**仅用于两个高层协议不同的网络互连**。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。 + +## OSI 和TCP/IP的区别 +1. OSI精确定义了服务、协议和接口,符合面向对象程序设计思想。而TCP/IP在这些概念上没有明确区分。 +2. OSI在产生协议之前没有偏向任何特定的协议,通用性良好,但设计没有太多经验不知道将哪些功能放到哪一层。TCP/IP,首先出现协议,模型实际上是对已有协议的描述。因此不会出现协议不能匹配的模式。 +3. TCP/IP考虑了异构网的互联问题,而OSI只考虑用一种标准的公用数据网将各种不同系统互连。 +4. OSI在网络层支持无连接和面向连接的通信,但在传输层仅有面向连接通信。而TCP/IP则相反,在网际层仅有无连接服务,在传输层支持无连接和面向连接两种模式。 + +## TCP与UDP的区别 +1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接 +2、TCP提供可靠全双功的通信服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP则是不可靠信道,尽最大努力交付,即不保证可靠交付 +3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的. +4.TCP具有拥塞控制,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等) +5、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信 +6、TCP首部开销20字节;UDP的首部开销小,只有8个字节. + +### TCP应用场景 +:效率要求相对低,但对准确性要求相对高的场景。因为传输中需要对数据确认、重发、排序等操作,相比之下效率没有UDP高。举几个例子:文件传输(准确高要求高、但是速度可以相对慢)、接受邮件、远程登录。 + +### UDP应用场景 +:效率要求相对高,对准确性要求相对低的场景。举几个例子:QQ聊天、在线视频、网络语音电话(即时通讯,速度要求高,但是出现偶尔断续不是太大问题,并且此处完全不可以使用重发机制)、广播通信(广播、多播)。 + +## TCP对应的协议和UDP对应的协议 +**TCP对应的协议**: +(1) FTP(21):定义了文件传输协议,使用21端口。常说某某计算机开了FTP服务便是启动了文件传输服务。下载文件,上传主页,都要用到FTP服务。 +(2) Telnet(23):(远程登陆协议)它是一种用于远程登陆的端口,用户可以以自己的身份远程连接到计算机上,通过这种端口可以提供一种基于DOS模式下的通信服务。如以前的BBS是-纯字符界面的,支持BBS的服务器将23端口打开,对外提供服务。 +(3) SMTP(25):定义了简单邮件传送协议,现在很多邮件服务器都用的是这个协议,用于发送邮件。如常见的免费邮件服务中用的就是这个邮件服务端口,所以在电子邮件设置-中常看到有这么SMTP端口设置这个栏,服务器开放的是25号端口。 +(4) POP3(110):它是和SMTP对应,POP3用于接收邮件。通常情况下,POP3协议所用的是110端口。也是说,只要你有相应的使用POP3协议的程序(例如Fo-xmail或Outlook),就可以不以Web方式登陆进邮箱界面,直接用邮件程序就可以收到邮件(如是163邮箱就没有必要先进入网易网站,再进入自己的邮-箱来收信)。 +(5)HTTP(80)协议:是从Web服务器传输超文本到本地浏览器的传送协议。 +**UDP对应的协议**: +(1) DNS(53):用于域名解析服务,将域名地址转换为IP地址。DNS用的是53号端口。 +(2) RIP:路由信息协议,端口520 +(2) SNMP(161):简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。 +(3) TFTP(69)(Trival File Transfer Protocal),简单文件传输协议,该协议在熟知端口69上使用UDP服务。 + +http://www.jianshu.com/p/8be9b3204864 +http://www.jianshu.com/p/eab86c0d1612 +## 常见的路由选择协议,以及它们的区别 +常见的路由选择协议有:RIP协议、OSPF协议。 +RIP协议(路由信息协议):底层是贝尔曼福特算法,**基于距离向量的路由选择协议**,它选择路由的度量标准(metric)是**跳数**,最大跳数是15跳,如果大于15跳,它就会丢弃数据包。仅和相邻路由器交换当前路由器所知道的全部信息。是应用层协议,使用UDP传输数据,端口520 +OSPF协议(开放最短路由优先):底层是迪杰斯特拉算法,**是链路状态路由选择协议**,它选择路由的度量标准是**带宽**,延迟。向本自治系统中所有路由器发送与本路由器相邻的所有路由器的链路状态,但这只是路由器知道的部分信息。网络层协议,直接IP数据报传输. + +## TCP报文首部 +源端口和目的端口,各占2个字节,分别写入源端口和目的端口; +序号,占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始; +确认号,占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701; +数据偏移,占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远; +保留,占6位,保留今后使用,但目前应都位0; +紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据; +**确认ACK**,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1; +推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1; +复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接; +**同步SYN**,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1; +**终止FIN**,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放; +窗口,占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受; +检验和,占2字节,校验首部和数据这两部分; +紧急指针,占2字节,指出本报文段中的紧急数据的字节数; +选项,长度可变,定义一些其他的可选的参数。 + +## TCP的三次握手与四次挥手过程,各个状态名称与含义,TIMEWAIT的作用 +**三次握手** +第一次握手:客户机首先向服务器的TCP发送一个连接请求报文段,这个特殊的报文段不含应用层数据,其首部中同步位 **SYN=1**。另外,客户机会随机选择一个起始序号 **seq=x**(连接请求报文不携带数据,但要消耗一个序号);客户端进程进入了 **SYN-SENT(同步已发送状态)状态** +第二次握手:服务器的TCP收到连接请求报文段后,如果同意建立连接,就向客户机发回确认,并为该TCP连接分配TCP缓存和变量。在确认报文段中,**SYN=1,ACK=1**,确认号字段值为 **ack=x+1**,并且服务器随机产生起始序号 **seq=y**. 确认包同样不包含应用层数据。 服务器进程进入了 **SYN-RCVD(同步收到)状态** +第三次握手:当客户机收到确认报文段后,还要向服务器给出确认,并且也要给该连接**分配缓存和变量**。这个报文段的确认为 **ACK=1**,序号段被设置为 **seq=x+1**,确认号字段 **ack=y+1**. 该报文段可以携带数据,如果不携带数据则不消耗序号。客户端进入 **ESTABLISHED(已建立连接)状态** +理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。因为TCP提供全双工通信,因此双方任何时候都可以发送数据。 + +### 为什么TCP客户端最后还要发送一次确认呢? + 一句话,主要 **防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误**。 + + 如果使用的是两次握手建立连接,假设有这样一种场景,**客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文**,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。 + + 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。 + +**四次挥手** +第一次挥手:客户机打算关闭连接,就向其TCP发送一个连接释放报文,并停止再发送数据,主动关闭TCP连接。该报文段的 **FIN=1**,**seq=u**,它等于前面已经发送过的数据的最后一个字节的序号加1。 客户端进入 **FIN-WAIT-1(终止等待1)状态** +第二次挥手:服务器收到连接释放报文段后即发出确认,确认号是ack=u+1,序号为v,等于它前面已经发送过的数据的最后一个字节序号加1.此时客户机到服务器这个方向的连接就释放了,TCP处于半关闭状态。**ACK=1,seq=v,ack=u+1**,服务端就进入了 **CLOSE-WAIT(关闭等待)状态** +客户端收到第二次挥手 ,客户端进入 **FIN-WAIT-2(终止等待2)状态** +第三次挥手:若服务器已经没有要向客户机发送的数据,就通知TCP释放连接,此时发出 **FIN=1**,确认号 **ack= u+1** ,序号 **seq =w**,已经发送过的数据最后一个字节加1。确认为ACK=1. 服务器就进入了 **LAST-ACK(最后确认)状态** +(**FIN = 1, ACK=1,seq = w, ack =u+1**) +第四次挥手:客户机收到连接释放报文段后,必须发出确认。在确认报文段中,确认位 **ACK=1**,序号 **seq=u+1**,确认号 **ack=w+1** . 此时连接还没有释放掉,**必须经过实践等待计时器设置的时间2MSL(Max Segment Lifetime),后**,客户机才进入连接关闭状态。 +(**ACK=1,seq=u+1,ack=w+1**) + +### 为什么客户端最后还要等待2MSL? + MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。 + + 第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,**站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,** 而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。 + + 第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。 + +### 为什么建立连接是三次握手,关闭连接确是四次挥手呢? + + 建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 + 而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而 **自己也未必全部数据都发送给对方了**,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。 + +### 如果已经建立了连接,但是客户端突然出现故障了怎么办? + TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。 + +https://blog.csdn.net/qzcsu/article/details/72861891 +http://www.cnblogs.com/Jessy/p/3535612.html + +## 为什么会采用三次握手,若采用二次握手可以吗? +采用三次握手是为了防止失效的连接请求报文段再次传到服务器,因而产生错误。如果由于网络不稳定,虽然客户端以前发送的连接请求以到达服务方,但服务方的同意连接的应答未能到达客户端。则客户方要重新发送连接请求,若采用二次握手,服务方收到客服端重传的请求连接后,会以为是新的请求,就会发送同意连接报文,并新开进程提供服务,这样会造成服务方资源的无谓浪费。 +如果只采用一次的话,客户端不知道服务端是否已经收到自己发送的数据,则会不断地发送数据。为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手 + + +## 为什么四次挥手,主动方要等待2MSL后才关闭连接. +一、保证TCP协议的全双工连接能够可靠关闭. +主要为了确保对方能受到ACK信息. 如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。所以,Client不是直接进入CLOSED,而是要保持2MSL,如果在这个时间内又收到了server的关闭请求时可以进行重传,否则说明server已经受到确认包则可以关闭. + + +https://www.zhihu.com/question/36930631 +## TCP拥塞控制 +为了更好对TCP进行拥塞控制,因特网建议标准定义了以下四种算法:慢开始,拥塞避免,快重传,快恢复。 +首先在TCP要求发送端维护两个窗口: +1) 接收窗口rwnd,接收方根据当前缓存大小锁许诺的最新窗口值。 +2) 拥塞窗口 cwnd ,发送方根据自己估算的网络拥塞程度而设置的窗口值。 +发送窗口的上限是取这两者的最小值。 +慢开始: TCP刚连接好时,先令拥塞窗口cwnd =1 ,在每次收到一个对新报文段的确认时将cwnd加1. Cwnd的大小呈指数增长。 +拥塞避免算法: 当cwnd大于等于慢开始门限ssthresh时,cwnd窗口每次加1而不是加倍。当发送方检测到**超时事件**的发生时,就将慢开始门限设置为当前cwnd的一半,同时将cwnd设置为1. 这样的目的是迅速减少主机发送到网络的分组数,使得发生拥塞的路由器有足够的时间吧队列中积压的分组处理完毕。 +快重传:当发送方连续收到三个重复的ACK报文时,直接重传对方尚未收到的报文段,而不必等待那个报文段设置的重传计时器超时。 +快恢复:当发送端收到连续三个冗余的ACK时,就执行“乘法减小”算法,把慢开始门限ssthresh减半,cwnd设置为慢开始门限减半后的数值(与慢开始不同)。 + +## TCP滑动窗口与回退N针协议 +滑动窗口: +发送方都维持一组连续的允许发送的帧的序号称为发送窗口。同时接收方也维持一组连续的允许接收的帧序号,称为接收窗口。发送窗口是用来对发送方进行流量控制,接收窗口是用来控制接收那些数据帧不可以接收那些帧。 +在发送端,收到一个确认帧,发送窗口就向前滑动一个帧位置,当发送窗口没有可以发送的帧时,发送方就停止发送。直到接收方发送的确认帧使发送窗口向前移动。 +在接收端,只有收到数据帧的序号落在接收窗口内才将该帧收下,否则一律丢弃。每收到一个帧后就发送回确认帧。 + +后退N帧协议 +发送窗口大于1,接收窗口等于1.在后退N帧中,发送方不需要收到上一帧的ACK后才能发送下一帧,而是可以连续发送帧。当接收方检测出失序信息帧后,要求发送方重发最后一个正确接收的帧之后的所有未被确认的帧。源站每发完一帧就要为该帧设置超时计时器,如果在超时时间内没有收到确认帧则进行重发。服务端会采用累积确认的方式,不是每个帧都发确认,可以连续收到好几个正确帧后发回一个确认信息。接收方因为窗口为1,所以必须按序接收数据帧,如果某个序大于当前所期望的序号时就会连续发送3个ACK确认帧,要求客户端重传失序帧。 + +## TCP的可靠性如何保证 +在TCP的连接中,数据流必须以正确的顺序送达对方。TCP的可靠性是通过顺序编号和确认(ACK)来实现的。TCP在开始传送一个段时,为准备重传而首先将该段插入到发送队列之中,同时启动时钟。其后,如果收到了接受端对该段的ACK信息,就将该段从队列中删去。如果在时钟规定的时间内,ACK未返回,那么就从发送队列中再次送出这个段。TCP在协议中就对数据可靠传输做了保障,握手与断开都需要通讯双方确认,数据传输也需要双方确认成功,在协议中还规定了:分包、重组、重传等规则;而UDP主要是面向不可靠连接的,不能保证数据正确到达目的地。 + +## Http的报文结构 +http请求由三部分组成,分别是:请求行、消息报头、请求正文 +方法 [空格] URL [空格] 版本 +首部字段名: [空格] 值 +… +首部字段名: [空格] 值 +[空一行] +实体主体 + +HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文 +版本[空格] 状态码 [空格] 短语 +首部字段名: [空格] 值 +… +首部字段名: [空格] 值 +[空一行] +实体主体 +更多http内容参考:http://www.cnblogs.com/maanshancss/p/4503385.html + +## Http request的几种类型 +HTTP协议中共定义了八种方法或者叫“动作”来表明对Request-URI指定的资源的不同操作方式,具体介绍如下: +GET:向特定的资源发出请求。 +POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。 +PUT:向指定资源位置上传其最新内容。 +DELETE:请求服务器删除Request-URI所标识的资源。 +HEAD:请求读取由URL所标志的信息的首部。 +OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送' * '的请求来测试服务器的功能性。 +TRACE:回显服务器收到的请求,主要用于测试或诊断。 +CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 + +## Http1.1和Http1.0的区别 +1)HTTP1.0 是短连接,HTTP1.1是长连接。 HTTP 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求。如果一个html包含多个图片或资源时需要多次与服务器建立连接。 HTTP 1.1支持持久连接,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接.HTTP 1.1采用了流水线的持久连接,即客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。 +2)HTTP 1.0不支持Host请求头字段,WEB浏览器无法使用主机头名来明确表示要访问服务器上的哪个WEB站点,这样就无法使用WEB服务器在同一个IP地址和端口号上配置多个虚拟WEB站点。在HTTP 1.1中增加Host请求头字段后,WEB浏览器可以使用主机头名来明确表示要访问服务器上的哪个WEB站点,这才实现了在一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点。 +3)HTTP 1.1还提供了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头 +4)带宽优化。HTTP/1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了。例如,客户端只需要显示一个文档的部分内容,又比如下载大文件时需要支持断点续传功能,而不是在发生断连后不得不重新下载完整的包。 +HTTP/1.1中在请求消息中引入了range头域,它允许只请求资源的某个部分。 +5) HTTP/1.1增加了OPTIONS方法,它允许客户端获取一个服务器支持的方法列表 + +http://blog.csdn.net/forgotaboutgirl/article/details/6936982 + +## Http怎么处理长连接 +HTTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持久连接支持。TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了带宽。 +使用长连接的HTTP协议,会在响应头有加入这行代码:Connection:keep-alive 。在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。 + +http://www.codeceo.com/article/http-long-connect.html + +## Cookie与Session的作用于原理 +会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。 +Cookie +Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就产生一个用户身份标识,然后在响应消息中将该标识号以Cookie的形式传递给浏览器.客户端浏览器会把Cookie保存起来。浏览器在以后每次访问该web服务器时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容. Cookie不能被浏览器共享 +Cookie具有不可跨域名性,例如浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Cookie的maxAge决定着Cookie的有效期,单位为秒(Second) +**默认情况下,cookie是一个会话级别的,用户退出浏览器后被删除** + +Session +Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。 +如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。 +Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。 + +session工作原理 +(1)web不会在客户端开始访问它时创建session,在访问特殊的程序并且该程序(servlet)决定与客户端开启会话时,服务器生成一个唯一值,称为Session ID(好像是通过取进程ID的方式取得的)。服务器开辟一块内存,对应于该Session ID。 +(2)服务器再将该Session ID写入浏览器的cookie。 +(3)服务器内有一进程,监视所有Session的活动状况,如果有Session超时或是主动关闭,服务器就释放改内存块。 +(4)当浏览器连入服务器时并请求Session时,服务器就读浏览器Cookie中的Session ID。 +(5)然后,服务检查该Session ID所对应的内存是否有效。 +(6)如果有效,就读出内存中的值。 +(7)如果无效,就建立新的Session。 + +**tomcat默认设置是30分钟** +具体设置很简单,方法有三种: +(1)在主页面或者公共页面中加入:session.setMaxInactiveInterval(900); +参数900单位是秒,即在没有活动15分钟后,session将失效。设置为-1将永不关闭。 +这里要注意这个session设置的时间是根据服务器来计算的,而不是客户端。所以如果是在调试程序,应该是修改服务器端时间来测试,而不是客户端。 +(2)也是比较通用的设置session失效时间的方法,就是在项目的web.xml中设置 + +15 + +这里的15也就是15分钟失效. +(3)直接在应用服务器中设置,如果是tomcat,可以在tomcat目录下conf/web.xml中 +找到元素,tomcat默认设置是30分钟,只要修改这个值就可以了。 +需要注意的是如果上述三个地方如果都设置了,有个优先级的问题,从高到低: +(1)-->(2)--->(3) + +生命周期: +1)tomcat默认是30分钟 +2)因为session和cookie有关系,客户端浏览器通过cookie维持该会话,cookie不支持跨浏览器共享,意味着如果把浏览器关该会闭的话该会话就会失效(但服务端还保存着)。因此同一机器的两个浏览器窗口访问服务器时,会生成两个不同的Session。 + +http://qiusuoge.com/10576.html +http://blog.csdn.net/colzer/article/details/8686966 +http://www.cnblogs.com/binger/archive/2013/03/19/2970171.html + +## 电脑上访问一个网页,整个过程是怎么样的:DNS、HTTP、TCP、OSPF、IP、ARP +1) 浏览器分析连接指向的页面URL(http://www.baidu.com) +2) 浏览器向DNS请求www.baidu.com.的IP地址 +3) 域名系统DNS解析出百度官网的服务器IP地址 +4) 浏览器与该服务器建立TCP连接(默认端口80) +5) 浏览器发出HTTP请求获取指定页面。 +6) 服务器通过HTTP响应把文件对应页面发送给浏览器。 +7) TCP连接释放。 +8) 浏览器将文件进行解析,并将web网页显示给用户。 + +## get提交和post提交的区别 +1.根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的。 +  (1).所谓安全的意味着该操作用于获取信息而非修改信息。换句话说,GET 请求一般不应产生副作用。就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。 +  (2).幂等的意味着对同一URL的多个请求应该返回同样的结果。 +2.根据HTTP规范,POST表示可能修改变服务器上的资源的请求。还是新闻以网站为例,读者对新闻发表自己的评论应该通过POST实现,因为在评论提交后站点的资源已经不同了,或者说资源被修改了。 +3.GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连.POST把提交的数据则放置在是HTTP包的包体中。 +4.GET安全性较低,POST安全性较高。因为GET在传输过程,数据被放在请求的URL中,而如今现有的很多服务器、代理服务器或者用户代理都会将请求URL记录到日志文件中,然后放在某个地方,这样就可能会有一些隐私的信息被第三方看到。另外,用户也可以在浏览器上直接看到提交的数据,一些系统内部消息将会一同显示在用户面前。 +5.get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。 +6.在FORM(表单)中,Method默认为"GET" + + +幂等(idempotent、idempotence)是一个数学或计算机学概念,常见于抽象代数中。 +  幂等有一下几种定义: +  对于单目运算,如果一个运算对于在范围内的所有的一个数多次进行该运算所得的结果和进行一次该运算所得的结果是一样的,那么我们就称该运算是幂等的。比如绝对值运算就是一个例子,在实数集中,有abs(a)=abs(abs(a))。 +  对于双目运算,则要求当参与运算的两个值是等值的情况下,如果满足运算结果与参与运算的两个值相等,则称该运算幂等,如求两个数的最大值的函数,有在在实数集中幂等,即max(x,x) = x。 +详见: http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html +http://www.cnblogs.com/skynet/archive/2010/05/18/1738301.html + +## https如何加密的 +HTTPS介绍: +HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议 它是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息。**它使用安全套接字层(SSL)进行信息交换**,简单来说它是HTTP的安全版。 它是由Netscape开发并内置于其浏览器中,使用SSL在发送方把原始数据进行加密,然后在接受方进行解密保证数据的安全性.然而,加密和解密过程需要耗费系统大量的开销,严重降低机器的性能. +HTTPS实际上就是SSL over HTTP,它使用默认端口**443**,而不是像HTTP那样使用端口80来和TCP/IP进行通信。HTTPS协议使用SSL在发送方把原始数据进行加密,然 后在接受方进行解密,加密和解密需要发送方和接受方通过交换共知的密钥来实现,因此,所传送的数据不容易被网络黑客截获和解密.然而,加密和解密过程需要耗费系统大量的开销,严重降低机器的性能,相关测试数据表明使用HTTPS协议传输数据的工作效率只有使用HTTP协议传输的十分之一。 + +如何实现加密:(其实就是sssl的交互过程) +HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。具体是如何进行加密,解密,验证的 + +http://blog.csdn.net/binyao02123202/article/details/8049446 +http://www.codeceo.com/article/why-http-better-than-https.html + +## http和https的区别 +1. https协议需要到ca申请证书,一般免费证书很少,需要交费。 +2. http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议 http和https使用的是完全不同的连接方式用的端口也不一样:前者是80,后者是443。 +3. http的连接很简单,是无状态的 HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全 HTTPS解决的问题. +http://www.admin5.com/article/20150708/608526.shtml + +## SSL协议及完整交互过程 +SSL是Netscape公司所提出的安全保密协议,在浏览器(如Internet Explorer、Netscape Navigator)和Web服务器(如Netscape的Netscape Enterprise Server、ColdFusion Server等等)之间构造安全通道来进行数据传输,SSL运行在TCP/IP层之上、应用层之下,为应用程序提供加密数据通道,它采用了RC4、MD5 以及RSA等加密算法,使用40 位的密钥,适用于商业信息的加密。 + +开始加密通信之前,客户端和服务器首先必须建立连接和交换参数,这个过程叫做握手(handshake)。 +**1 客户端发出请求(ClientHello)** +首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,这被叫做ClientHello请求。在这一步,客户端主要向服务器提供以下信息。 +(1) 支持的协议版本,比如TLS 1.0版。 +(2) 一个客户端生成的随机数,稍后用于生成"对话密钥"。 +(3) 支持的加密方法,比如RSA公钥加密。 +(4) 支持的压缩方法。 + +**4.2 服务器回应(SeverHello)** +服务器收到客户端请求后,向客户端发出回应,这叫做SeverHello。服务器的回应包含以下内容: +(1) 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。 +(2) 一个服务器生成的随机数,稍后用于生成"对话密钥"。 +(3) 确认使用的加密方法,比如RSA公钥加密。 +(4) 服务器证书。(公钥) +**4.3 客户端回应** +客户端收到服务器回应以后,首先验证服务器证书。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。 +如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后,向服务器发送下面三项信息。 +(1) 一个随机数。该随机数用服务器公钥加密,防止被窃听。 +(2) 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。 +(3) 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。 +上面第一项的随机数,是整个握手阶段出现的第三个随机数,又称"pre-master key"。有了它以后,客户端和服务器就同时有了三个随机数,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把"会话密钥"。(会话秘钥是采用对称加密方式,而这里的公钥是采用非对称加密) +**4 服务器的最后回应** +服务器通过私钥解密收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的"会话密钥"。然后,向客户端最后发送下面信息。 +(1)编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。 +(2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。 +至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容。 + +至于为什么一定要用三个随机数,来生成"会话密钥",dog250解释得很好: +"不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。 +对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。 +pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。" + +http://limboy.me/tech/2011/02/19/https-workflow.html +http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html +http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html +http://kb.cnblogs.com/page/162080/ + +## https处理的一个过程,对称加密和非对称加密(参考上一条,这一条就是通俗的表示) +1. SSL原理很简单。当你的浏览器向服务器请求一个安全的网页(通常是 https://) +2. 服务器就把它的证书和公匙发回来 +3. 浏览器检查证书是不是由可以信赖的机构颁发的,确认证书有效和此证书是此网站的。 +4. 浏览器使用公钥加密了一个随机对称密钥,包括加密的URL一起发送到服务器。 +5. 服务器用自己的私匙解密了你发送的钥匙。然后用这把对称加密的钥匙给你请求的URL链接解密。 +6. 服务器用你发的对称钥匙给你请求的网页加密。你也有相同的钥匙就可以解密发回来的网页了 + +加密算法绝大部分都属于以下两种加密类型之一: +对称加密:加密解密用的是同样的“钥匙” +非对称加密:加密解密用的是不同的“钥匙” + +对称加密 +Alice 在盒子里放有信息,盒子上有挂锁,她有钥匙。通过邮局她把这个盒子寄给Bob。Bob收到盒子后,用相同的钥匙打开盒子(钥匙之前就得到了,可能是Alice面对面给他的)。然后Bob可以用同样的方法回复。 + +非对称加密 +Bob和Alice各有自己的盒子。Alice要跟Bob秘密通信,她先让Bob把开着的盒子通过邮局发给她。Alice拿到盒子后放入信息锁上,然后发给Bob。Bob就可以用他自己的钥匙打开了。回复的话就用同样的方法。 +非对称算法在加密和解密时用的是不同的钥匙。信息接受者有两把钥匙:一把“公匙”,一把“私匙”。公匙是给信息发送者用来加密的,私匙是自己用来解密的。这样最大的好处是:不必通过不安全的渠道发送私密的东西。公匙本来就是给别人用的,不用藏好。你的私匙在你产生私匙的电脑里保存着。 + +http://article.yeeyan.org/view/90729/174903/ + +## Http和https的区别 + - http是HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份 + - https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对 + - 加密,但对称加密的密钥用服务器方的证书进行了非对称加密。此外客户端可以验证服务器端的身份 + - 如果配置了客户端验证,服务器方也可以验证客户端的身份。 + - https协议需要到ca申请证书,一般免费证书很少,需要交费。 + - http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议 + - http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。 + - http的连接很简单,是无状态的 + - HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全 + +https://github.com/Wl201314/MartinBlog/tree/master/Blog/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80 +## DNS域名系统,简单描述其工作原理。 +域名系统DNS是因特网使用的命名系统,用于把便于人们记忆的含有特定含义的主机名转换为便于机器处理的IP地址。DNS系统采用C/S模式,其协议运行在UDP上,使用53号端口。从概念上讲DNS可以分为3个部分:层次域名空间,域名服务器和解析器。 + +域名解析是把域名映射成IP地址或者把IP地址映射成域名的过程。域名解析有两种方式:递归查询和迭代查询。 +递归查询:如果本地主机询问的本地域名服务器不知道被查询的域名IP地址,那么**本地域名服务器**就以DNS客户的身份,向**根域名服务器**继续发出查询请求报文,而不是自己进行下一步非查询。根域名服务器会继续向**顶级域名服务器**查询请求,如果存在则直接返回给根服务器,否则顶级域名服务器向对应的**权限域名服务器**查询。是一种递归的查询方式。 + +迭代查询:如果本地主机询问的本地域名服务器不知道被查询的域名IP地址,那么本地域名服务器就以DNS客户的身份,向根域名服务器继续发出查询请求报文。跟服务器收到请求报文时,要么给出所有查询的IP地址,要么告诉本地域名服务器下一步需要查询的顶级域名服务器。然后本地服务器向这个顶级域名服务器进行后续的查询。同样的顶级域名服务器收到查询报文后,要么给出所要查询的IP地址,要么告诉本地域名服务器下一步应该查找那个权限域名服务器。 + +## 面向连接和非面向连接的服务的特点是什么? +面向连接的服务:通信双方进行通信之前,必须先建立连接,在通信过程中,整个连接情况一直都是被实时地监控和管理。当通信结束后,则应释放这个连接。 +无连接服务:两个实体之间的通信不需要先建立好连接,需要通信的时候,直接将信息发送到”网络”中,让该信息的传递在网上尽力而为地往目的地传送。 + +## 端口及对应的服务? +FTP 21 SSH 22 telnet 23 SMTP 25 Domain(域名服务器) 53 HTTP 80 +POP3 110 NTP(网络时间协议)123 MySQL数据库服务3306 https 443 SNMP(161) TFTP(69) +Shell或 cmd 514 POP-2 109 SQL Server 1433 + +## 各种协议 +ICMP协议: 因特网控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。 +TFTP协议: 是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。 +HTTP协议: 超文本传输协议,是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。 +DHCP协议: 动态主机配置协议,是一种让系统得以连接到网络上,并获取所需要的配置参数手段。 +NAT协议:网络地址转换属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术, +DHCP协议:一个局域网的网络协议,使用UDP协议工作,用途:给内部网络或网络服务供应商自动分配IP地址,给用户或者内部网络管理员作为对所有计算机作中央管理的手段。 + +## Ping的整个过程 +同一个局域网中: +1、Pc1在应用层发起个目标IP位IP2的Ping请求。 +2、传输层接到上层请求的数据,将数据分段并加上UDP报头。下传到Internet层。 +3、 网际层接收来处上层的数据后,根据ICMP协议进行封装,添加PC1的IP为源IP为和PC2IP为目标IP后封装成数据包。下传到网络接口层。 +4、网络接口层接收数据包后,进行封装,源MAC地址为PC1的MAC地址,目标MAC地址则查询自己的ARP缓存表获取。如果PC1 arp缓存表中没有目标IP对应的MAC地址,则PC1发出一个ARP广播报文。ARP报文中源MAC地址为Pc1mac地址,源IP地址为pc1 IP,所要请求的是PC2的IP对应的mac地址。 +5、PC2收到ARP广播后,进行解封装,发现所请求的MAC地址是自己的。则PC2将PC1的mac地址写入arp缓存表中。然后向PC1发送一个 ARP应答单播。该单播消息包括目标IP为PC1ip,目标Mac为pc1mac地址,源IP为PC2的IP,源Mac为pc2的Mac。 +6、Pc1接收到PC2的arp应答报文后,将Pc2的MAC地址存入arp缓存中,并将Pc2的Mac地址作为目标地址封装到数据帧中。发给下层进行网络传输。 +7、PC2接收这个帧后,在网络接口层查看目标mac地址是否指向自己。是,PC2则将帧头去掉,向上层传输。 +8、Pc2网际层接收到这个信息包,查看包头,发现目标IP和自己匹配,则解封装,将数据向上层传输。 +9、传输层接收来自下层的Ping请求的UDP报文,则去掉UDP报头,向应用层传送。 +10、应用层收到ping请求后,发送一个PIng回应报文给PC1 +http://blog.chinaunix.net/uid-26758209-id-3146224.html + +## ICMP协议: +1) ICMP允许主机或路由报告差错情况和提供有关异常情况。ICMP是因特网的标准协议,但ICMP不是高层协议,而是IP层的协议。通常ICMP报文被IP层或更高层协议(TCP或UDP)使用。一些ICMP报文把差错报文返回给用户进程。 +2) ICMP报文作为IP层数据报的数据,加上数据报的首部,组成数据报发送出去。 +3) ICMP报文的种类有两种,即ICMP差错报告报文和ICMP询问报文。 + +差错报告 +ICMP差错报告报文共有5种: + 终点不可达:终点不可达分为:网络不可达,主机不可达,协议不可达,端口不可达,需要分片但DF比特已置为1,以及源路由失败等六种情况,其代码字段分别置为0至5。当出现以上六种情况时就向源站发送终点不可达报文。 +说明: +端口不可达:UDP的规则之一是:如果收到UDP数据报而且目的端口与某个正在使用的进程不相符,那么UDP返回一个ICMP不可达报文。 +源站抑制:当路由器或主机由于拥塞而丢弃数据报时,就向源站发送源站抑制报文,使源站知道应当将数据报的发送速率放慢。 +时间超过:当路由器收到生存时间为零的数据报时,除丢弃该数据报外,还要向源站发送时间超过报文。当目的站在预先规定的时间内不能收到一个数据报的全部数据报片时,就将已收到的数据报片都丢弃,并向源站发送时间超过报文。 +参数问题:当路由器或目的主机收到的数据报的首部中的字段的值不正确时,就丢弃该数据报,并向源站发送参数问题报文。 +改变路由(重定向)路由器将改变路由报文发送给主机,让主机知道下次应将数据报发送给另外的路由器。 + +询问报文 +ICMP询问报文有四种 +**回送请求和回答**,ICMP回送请求报文是由主机或路由器向一个特定的目的主机发出的询问。收到此报文的机器必须给源主机发送ICMP回送应答报文。这种询问报文用来测试目的站是否可达以及了解其有关状态 +**时间戳请求和回答**:ICMP时间戳请求允许系统向另一个系统查询当前的时间。该ICMP报文的好处是它提供了毫秒级的分辨率,而利用其他方法从别的主机获取的时间只能提供秒级的分辨率。请求端填写发起时间,然后发送报文。应答系统收到请求报文时填写接收时间戳,在发送应答时填写发送时间戳。大多数的实现是把后面两个字段都设成相同的值。 +**掩码地址请求和回答**:主机使用ICMP地址掩码请求报文可向子网掩码服务器得到某个接口的地址掩码。 +**路由器询问和通过**:主机使用ICMP路由器询问和通过报文可了解连接在本网络上的路由器是否正常工作。主机将路由器询问报文进行广播(或多播)。收到询问报文的一个或几个路由器就使用路由器通过报文广播其路由选择信息 + +## C/S模式下使用socket通信,几个关键函数 + +## 知识点: +1) SSP通过七号信令网实现与SAU的连接,而SCP与SAU之间通过TCP/IP协议连接。 +2) 重组发生在目的主机,分片发生在路由器上 diff --git "a/000 - 1 Computer Basics/04 \344\272\222\350\201\224\347\275\221\345\215\217\350\256\256.txt" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/04 \344\272\222\350\201\224\347\275\221\345\215\217\350\256\256.txt" similarity index 100% rename from "000 - 1 Computer Basics/04 \344\272\222\350\201\224\347\275\221\345\215\217\350\256\256.txt" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/04 \344\272\222\350\201\224\347\275\221\345\215\217\350\256\256.txt" diff --git a/000 - 1 Computer Basics/Network/Http_Code.md "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/Http_Code.md" similarity index 100% rename from 000 - 1 Computer Basics/Network/Http_Code.md rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/Http_Code.md" diff --git "a/000 - 1 Computer Basics/Network/Http\345\215\217\350\256\256.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/Http\345\215\217\350\256\256.md" similarity index 100% rename from "000 - 1 Computer Basics/Network/Http\345\215\217\350\256\256.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/Http\345\215\217\350\256\256.md" diff --git a/000 - 1 Computer Basics/Network/Socket.md "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/Socket.md" similarity index 100% rename from 000 - 1 Computer Basics/Network/Socket.md rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/Socket.md" diff --git "a/000 - 1 Computer Basics/Network/TCP\344\270\216UDP.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/TCP\344\270\216UDP.md" similarity index 100% rename from "000 - 1 Computer Basics/Network/TCP\344\270\216UDP.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/TCP\344\270\216UDP.md" diff --git "a/000 - 1 Computer Basics/Network/\344\273\200\344\271\210\346\230\257SSL.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/\344\273\200\344\271\210\346\230\257SSL.md" similarity index 100% rename from "000 - 1 Computer Basics/Network/\344\273\200\344\271\210\346\230\257SSL.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/\344\273\200\344\271\210\346\230\257SSL.md" diff --git "a/000 - 1 Computer Basics/Network/\345\257\271\344\272\216Ping\347\232\204\350\277\207\347\250\213\357\274\214\344\275\240\347\234\237\347\232\204\344\272\206\350\247\243\345\220\227\357\274\237.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/\345\257\271\344\272\216Ping\347\232\204\350\277\207\347\250\213\357\274\214\344\275\240\347\234\237\347\232\204\344\272\206\350\247\243\345\220\227\357\274\237.md" similarity index 100% rename from "000 - 1 Computer Basics/Network/\345\257\271\344\272\216Ping\347\232\204\350\277\207\347\250\213\357\274\214\344\275\240\347\234\237\347\232\204\344\272\206\350\247\243\345\220\227\357\274\237.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/\345\257\271\344\272\216Ping\347\232\204\350\277\207\347\250\213\357\274\214\344\275\240\347\234\237\347\232\204\344\272\206\350\247\243\345\220\227\357\274\237.md" diff --git "a/000 - 1 Computer Basics/Network/\347\275\221\351\241\265\350\257\267\346\261\202\350\277\207\347\250\213.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/\347\275\221\351\241\265\350\257\267\346\261\202\350\277\207\347\250\213.md" similarity index 97% rename from "000 - 1 Computer Basics/Network/\347\275\221\351\241\265\350\257\267\346\261\202\350\277\207\347\250\213.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/\347\275\221\351\241\265\350\257\267\346\261\202\350\277\207\347\250\213.md" index 0821e039..e810c0b0 100644 --- "a/000 - 1 Computer Basics/Network/\347\275\221\351\241\265\350\257\267\346\261\202\350\277\207\347\250\213.md" +++ "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/\347\275\221\351\241\265\350\257\267\346\261\202\350\277\207\347\250\213.md" @@ -1,9 +1,9 @@ -1 查询域名对应的IP地址 (**DNS** Domain Name System) -2 向目标IP TCP三次握手建立连接 -3 发送Http请求 -4 服务器处理请求(**CDN** Content Delivery Network) -5 响应 -6 浏览器渲染显示 - -ARP 地址解析协议 IP MAC对应关系表 -RARP 反地址解析协议 +1 查询域名对应的IP地址 (**DNS** Domain Name System) +2 向目标IP TCP三次握手建立连接 +3 发送Http请求 +4 服务器处理请求(**CDN** Content Delivery Network) +5 响应 +6 浏览器渲染显示 + +ARP 地址解析协议 IP MAC对应关系表 +RARP 反地址解析协议 diff --git "a/000 - 1 Computer Basics/Network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\237\272\347\241\200\346\261\207\346\200\273.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\237\272\347\241\200\346\261\207\346\200\273.md" similarity index 100% rename from "000 - 1 Computer Basics/Network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\237\272\347\241\200\346\261\207\346\200\273.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/Network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\237\272\347\241\200\346\261\207\346\200\273.md" diff --git "a/000 - 1 Computer Basics/OperatingSystem/Linux\347\263\273\347\273\237\347\232\204IPC.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/OperatingSystem/Linux\347\263\273\347\273\237\347\232\204IPC.md" similarity index 100% rename from "000 - 1 Computer Basics/OperatingSystem/Linux\347\263\273\347\273\237\347\232\204IPC.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/OperatingSystem/Linux\347\263\273\347\273\237\347\232\204IPC.md" diff --git "a/000 - 1 Computer Basics/OperatingSystem/\346\223\215\344\275\234\347\263\273\347\273\237.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/OperatingSystem/\346\223\215\344\275\234\347\263\273\347\273\237.md" similarity index 100% rename from "000 - 1 Computer Basics/OperatingSystem/\346\223\215\344\275\234\347\263\273\347\273\237.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/OperatingSystem/\346\223\215\344\275\234\347\263\273\347\273\237.md" diff --git a/000 - 1 Computer Basics/img/2843224-46fb935cd31addbd.png "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/img/2843224-46fb935cd31addbd.png" similarity index 100% rename from 000 - 1 Computer Basics/img/2843224-46fb935cd31addbd.png rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/img/2843224-46fb935cd31addbd.png" diff --git a/000 - 1 Computer Basics/img/2843224-56f2056f0b36009f.png "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/img/2843224-56f2056f0b36009f.png" similarity index 100% rename from 000 - 1 Computer Basics/img/2843224-56f2056f0b36009f.png rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/img/2843224-56f2056f0b36009f.png" diff --git a/000 - 1 Computer Basics/img/2843224-e0854f19c817c83c.png "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/img/2843224-e0854f19c817c83c.png" similarity index 100% rename from 000 - 1 Computer Basics/img/2843224-e0854f19c817c83c.png rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/img/2843224-e0854f19c817c83c.png" diff --git a/000 - 1 Computer Basics/product.md "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/product.md" similarity index 100% rename from 000 - 1 Computer Basics/product.md rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/product.md" diff --git "a/000 - 1 Computer Basics/\345\237\272\347\241\200.txt" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\345\237\272\347\241\200.txt" similarity index 100% rename from "000 - 1 Computer Basics/\345\237\272\347\241\200.txt" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\345\237\272\347\241\200.txt" diff --git "a/000 - 1 Computer Basics/\347\241\254\347\233\230\345\237\272\346\234\254\347\237\245\350\257\206\357\274\210\347\243\201\345\244\264\343\200\201\347\243\201\351\201\223\343\200\201\346\211\207\345\214\272\343\200\201\346\237\261\351\235\242\357\274\211.md" "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\241\254\347\233\230\345\237\272\346\234\254\347\237\245\350\257\206\357\274\210\347\243\201\345\244\264\343\200\201\347\243\201\351\201\223\343\200\201\346\211\207\345\214\272\343\200\201\346\237\261\351\235\242\357\274\211.md" similarity index 98% rename from "000 - 1 Computer Basics/\347\241\254\347\233\230\345\237\272\346\234\254\347\237\245\350\257\206\357\274\210\347\243\201\345\244\264\343\200\201\347\243\201\351\201\223\343\200\201\346\211\207\345\214\272\343\200\201\346\237\261\351\235\242\357\274\211.md" rename to "000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\241\254\347\233\230\345\237\272\346\234\254\347\237\245\350\257\206\357\274\210\347\243\201\345\244\264\343\200\201\347\243\201\351\201\223\343\200\201\346\211\207\345\214\272\343\200\201\346\237\261\351\235\242\357\274\211.md" index ef03ef16..64fe6aae 100644 --- "a/000 - 1 Computer Basics/\347\241\254\347\233\230\345\237\272\346\234\254\347\237\245\350\257\206\357\274\210\347\243\201\345\244\264\343\200\201\347\243\201\351\201\223\343\200\201\346\211\207\345\214\272\343\200\201\346\237\261\351\235\242\357\274\211.md" +++ "b/000 - 1 Computer Basics \350\256\241\347\256\227\346\234\272\345\237\272\347\241\200/\347\241\254\347\233\230\345\237\272\346\234\254\347\237\245\350\257\206\357\274\210\347\243\201\345\244\264\343\200\201\347\243\201\351\201\223\343\200\201\346\211\207\345\214\272\343\200\201\346\237\261\351\235\242\357\274\211.md" @@ -1,64 +1,64 @@ -https://www.jianshu.com/p/9aa66f634ed6 -### 概述 -盘片(platter) -磁头(head) -磁道(track) -扇区(sector) -柱面(cylinder) - -### 盘片 片面 和 磁头 -硬盘中一般会有多个盘片组成,每个盘片包含两个面,每个盘面都对应地有一个读/写磁头。受到硬盘整体体积和生产成本的限制,盘片数量都受到限制,一般都在5片以内。盘片的编号自下向上从0开始,如最下边的盘片有0面和1面,再上一个盘片就编号为2面和3面。 -如下图: - - - - -### 扇区 和 磁道 -下图显示的是一个盘面,盘面中一圈圈灰色同心圆为一条条磁道,从圆心向外画直线,可以将磁道划分为若干个弧段,每个磁道上一个弧段被称之为一个扇区(图践绿色部分)。扇区是磁盘的最小组成单元,通常是512字节。(由于不断提高磁盘的大小,部分厂商设定每个扇区的大小是4096字节) - - - - -### 磁头 和 柱面 -硬盘通常由重叠的一组盘片构成,每个盘面都被划分为数目相等的磁道,并从外缘的“0”开始编号,具有相同编号的磁道形成一个圆柱,称之为磁盘的柱面。磁盘的柱面数与一个盘面上的磁道数是相等的。由于每个盘面都有自己的磁头,因此,盘面数等于总的磁头数。 如下图 - - - - -### 磁盘容量计算 - -存储容量 = 磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数 - -图3中磁盘是一个 3个圆盘6个磁头,7个柱面(每个盘片7个磁道) 的磁盘,图3中每条磁道有12个扇区,所以此磁盘的容量为: - -存储容量 6 * 7 * 12 * 512 = 258048 - - **每个磁道的扇区数一样是说的老的硬盘,外圈的密度小,内圈的密度大,每圈可存储的数据量是一样的。新的硬盘数据的密度都一致,这样磁道的周长越长,扇区就越多,存储的数据量就越大。** - -### 磁盘读取响应时间 -寻道时间:磁头从开始移动到数据所在磁道所需要的时间,寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms,一般都在10ms左右。 -旋转延迟:盘片旋转将请求数据所在扇区移至读写磁头下方所需要的时间,旋转延迟取决于磁盘转速。普通硬盘一般都是7200rpm,慢的5400rpm。 -数据传输时间:完成传输所请求的数据所需要的时间。 -小结一下:从上面的指标来看、其实最重要的、或者说、我们最关心的应该只有两个:寻道时间;旋转延迟。 -读写一次磁盘信息所需的时间可分解为:寻道时间、延迟时间、传输时间。为提高磁盘传输效率,软件应着重考虑减少寻道时间和延迟时间。 - -### 块/簇 -概述 -磁盘块/簇(虚拟出来的)。 块是操作系统中最小的逻辑存储单位。操作系统与磁盘打交道的最小单位是磁盘块。 -通俗的来讲,在Windows下如NTFS等文件系统中叫做簇;在Linux下如Ext4等文件系统中叫做块(block)。每个簇或者块可以包括2、4、8、16、32、64…2的n次方个扇区。 - -### 为什么存在磁盘块? -读取方便:由于扇区的数量比较小,数目众多在寻址时比较困难,所以操作系统就将相邻的扇区组合在一起,形成一个块,再对块进行整体的操作。 - -分离对底层的依赖:操作系统忽略对底层物理存储结构的设计。通过虚拟出来磁盘块的概念,在系统中认为块是最小的单位。 - -### page -操作系统经常与内存和硬盘这两种存储设备进行通信,类似于“块”的概念,都需要一种虚拟的基本单位。所以,与内存操作,是虚拟一个页的概念来作为最小单位。与硬盘打交道,就是以块为最小单位。 - -### 扇区、块/簇、page的关系 - -扇区: 硬盘的最小读写单元 -块/簇: 是操作系统针对硬盘读写的最小单元 -page: 是内存与操作系统之间操作的最小单元。 - -扇区 <= 块/簇 <= page +https://www.jianshu.com/p/9aa66f634ed6 +### 概述 +盘片(platter) +磁头(head) +磁道(track) +扇区(sector) +柱面(cylinder) + +### 盘片 片面 和 磁头 +硬盘中一般会有多个盘片组成,每个盘片包含两个面,每个盘面都对应地有一个读/写磁头。受到硬盘整体体积和生产成本的限制,盘片数量都受到限制,一般都在5片以内。盘片的编号自下向上从0开始,如最下边的盘片有0面和1面,再上一个盘片就编号为2面和3面。 +如下图: + + + + +### 扇区 和 磁道 +下图显示的是一个盘面,盘面中一圈圈灰色同心圆为一条条磁道,从圆心向外画直线,可以将磁道划分为若干个弧段,每个磁道上一个弧段被称之为一个扇区(图践绿色部分)。扇区是磁盘的最小组成单元,通常是512字节。(由于不断提高磁盘的大小,部分厂商设定每个扇区的大小是4096字节) + + + + +### 磁头 和 柱面 +硬盘通常由重叠的一组盘片构成,每个盘面都被划分为数目相等的磁道,并从外缘的“0”开始编号,具有相同编号的磁道形成一个圆柱,称之为磁盘的柱面。磁盘的柱面数与一个盘面上的磁道数是相等的。由于每个盘面都有自己的磁头,因此,盘面数等于总的磁头数。 如下图 + + + + +### 磁盘容量计算 + +存储容量 = 磁头数 × 磁道(柱面)数 × 每道扇区数 × 每扇区字节数 + +图3中磁盘是一个 3个圆盘6个磁头,7个柱面(每个盘片7个磁道) 的磁盘,图3中每条磁道有12个扇区,所以此磁盘的容量为: + +存储容量 6 * 7 * 12 * 512 = 258048 + + **每个磁道的扇区数一样是说的老的硬盘,外圈的密度小,内圈的密度大,每圈可存储的数据量是一样的。新的硬盘数据的密度都一致,这样磁道的周长越长,扇区就越多,存储的数据量就越大。** + +### 磁盘读取响应时间 +寻道时间:磁头从开始移动到数据所在磁道所需要的时间,寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms,一般都在10ms左右。 +旋转延迟:盘片旋转将请求数据所在扇区移至读写磁头下方所需要的时间,旋转延迟取决于磁盘转速。普通硬盘一般都是7200rpm,慢的5400rpm。 +数据传输时间:完成传输所请求的数据所需要的时间。 +小结一下:从上面的指标来看、其实最重要的、或者说、我们最关心的应该只有两个:寻道时间;旋转延迟。 +读写一次磁盘信息所需的时间可分解为:寻道时间、延迟时间、传输时间。为提高磁盘传输效率,软件应着重考虑减少寻道时间和延迟时间。 + +### 块/簇 +概述 +磁盘块/簇(虚拟出来的)。 块是操作系统中最小的逻辑存储单位。操作系统与磁盘打交道的最小单位是磁盘块。 +通俗的来讲,在Windows下如NTFS等文件系统中叫做簇;在Linux下如Ext4等文件系统中叫做块(block)。每个簇或者块可以包括2、4、8、16、32、64…2的n次方个扇区。 + +### 为什么存在磁盘块? +读取方便:由于扇区的数量比较小,数目众多在寻址时比较困难,所以操作系统就将相邻的扇区组合在一起,形成一个块,再对块进行整体的操作。 + +分离对底层的依赖:操作系统忽略对底层物理存储结构的设计。通过虚拟出来磁盘块的概念,在系统中认为块是最小的单位。 + +### page +操作系统经常与内存和硬盘这两种存储设备进行通信,类似于“块”的概念,都需要一种虚拟的基本单位。所以,与内存操作,是虚拟一个页的概念来作为最小单位。与硬盘打交道,就是以块为最小单位。 + +### 扇区、块/簇、page的关系 + +扇区: 硬盘的最小读写单元 +块/簇: 是操作系统针对硬盘读写的最小单元 +page: 是内存与操作系统之间操作的最小单元。 + +扇区 <= 块/簇 <= page diff --git a/000 - 2 Data & Algorithm/Algorithm/LeetCode/two-sum.md "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/LeetCode/two-sum.md" similarity index 100% rename from 000 - 2 Data & Algorithm/Algorithm/LeetCode/two-sum.md rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/LeetCode/two-sum.md" diff --git a/000 - 2 Data & Algorithm/Algorithm/LeetCode/zigzag-conversion.md "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/LeetCode/zigzag-conversion.md" similarity index 100% rename from 000 - 2 Data & Algorithm/Algorithm/LeetCode/zigzag-conversion.md rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/LeetCode/zigzag-conversion.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/Lookup/\346\212\230\345\215\212\346\237\245\346\211\276.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Lookup/\346\212\230\345\215\212\346\237\245\346\211\276.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/Lookup/\346\212\230\345\215\212\346\237\245\346\211\276.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Lookup/\346\212\230\345\215\212\346\237\245\346\211\276.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/Lookup/\351\241\272\345\272\217\346\237\245\346\211\276.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Lookup/\351\241\272\345\272\217\346\237\245\346\211\276.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/Lookup/\351\241\272\345\272\217\346\237\245\346\211\276.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Lookup/\351\241\272\345\272\217\346\237\245\346\211\276.md" diff --git a/000 - 2 Data & Algorithm/Algorithm/README.md "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/README.md" similarity index 100% rename from 000 - 2 Data & Algorithm/Algorithm/README.md rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/README.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/Sort/\345\206\222\346\263\241\346\216\222\345\272\217.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\345\206\222\346\263\241\346\216\222\345\272\217.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/Sort/\345\206\222\346\263\241\346\216\222\345\272\217.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\345\206\222\346\263\241\346\216\222\345\272\217.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/Sort/\345\275\222\345\271\266\346\216\222\345\272\217.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\345\275\222\345\271\266\346\216\222\345\272\217.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/Sort/\345\275\222\345\271\266\346\216\222\345\272\217.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\345\275\222\345\271\266\346\216\222\345\272\217.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/Sort/\345\277\253\351\200\237\346\216\222\345\272\217.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\345\277\253\351\200\237\346\216\222\345\272\217.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/Sort/\345\277\253\351\200\237\346\216\222\345\272\217.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\345\277\253\351\200\237\346\216\222\345\272\217.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/Sort/\346\216\222\345\272\217.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\346\216\222\345\272\217.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/Sort/\346\216\222\345\272\217.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\346\216\222\345\272\217.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/Sort/\351\200\211\346\213\251\346\216\222\345\272\217.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\351\200\211\346\213\251\346\216\222\345\272\217.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/Sort/\351\200\211\346\213\251\346\216\222\345\272\217.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\351\200\211\346\213\251\346\216\222\345\272\217.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/Sort/\351\235\242\350\257\225\344\270\255\347\232\204 10 \345\244\247\346\216\222\345\272\217\347\256\227\346\263\225\346\200\273\347\273\223.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\351\235\242\350\257\225\344\270\255\347\232\204 10 \345\244\247\346\216\222\345\272\217\347\256\227\346\263\225\346\200\273\347\273\223.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/Sort/\351\235\242\350\257\225\344\270\255\347\232\204 10 \345\244\247\346\216\222\345\272\217\347\256\227\346\263\225\346\200\273\347\273\223.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/Sort/\351\235\242\350\257\225\344\270\255\347\232\204 10 \345\244\247\346\216\222\345\272\217\347\256\227\346\263\225\346\200\273\347\273\223.md" diff --git a/000 - 2 Data & Algorithm/Algorithm/section01.md "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/section01.md" similarity index 100% rename from 000 - 2 Data & Algorithm/Algorithm/section01.md rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/section01.md" diff --git a/000 - 2 Data & Algorithm/Algorithm/section02.md "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/section02.md" similarity index 100% rename from 000 - 2 Data & Algorithm/Algorithm/section02.md rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/section02.md" diff --git a/000 - 2 Data & Algorithm/Algorithm/string.md "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/string.md" similarity index 100% rename from 000 - 2 Data & Algorithm/Algorithm/string.md rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/string.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/1.\344\270\203\347\247\215\346\226\271\345\274\217\345\256\236\347\216\260singleton\346\250\241\345\274\217.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/1.\344\270\203\347\247\215\346\226\271\345\274\217\345\256\236\347\216\260singleton\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/1.\344\270\203\347\247\215\346\226\271\345\274\217\345\256\236\347\216\260singleton\346\250\241\345\274\217.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/1.\344\270\203\347\247\215\346\226\271\345\274\217\345\256\236\347\216\260singleton\346\250\241\345\274\217.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/2.\344\272\214\347\273\264\346\225\260\347\273\204\344\270\255\347\232\204\346\237\245\346\211\276.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/2.\344\272\214\347\273\264\346\225\260\347\273\204\344\270\255\347\232\204\346\237\245\346\211\276.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/2.\344\272\214\347\273\264\346\225\260\347\273\204\344\270\255\347\232\204\346\237\245\346\211\276.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/2.\344\272\214\347\273\264\346\225\260\347\273\204\344\270\255\347\232\204\346\237\245\346\211\276.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\345\220\210\345\271\266\344\270\244\344\270\252\346\216\222\345\272\217\347\232\204\351\223\276\350\241\250.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\345\220\210\345\271\266\344\270\244\344\270\252\346\216\222\345\272\217\347\232\204\351\223\276\350\241\250.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\345\220\210\345\271\266\344\270\244\344\270\252\346\216\222\345\272\217\347\232\204\351\223\276\350\241\250.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\345\220\210\345\271\266\344\270\244\344\270\252\346\216\222\345\272\217\347\232\204\351\223\276\350\241\250.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\346\227\213\350\275\254\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\346\227\213\350\275\254\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\346\227\213\350\275\254\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\346\227\213\350\275\254\346\225\260\347\273\204\347\232\204\346\234\200\345\260\217\346\225\260\345\255\227.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23011\357\274\232\346\225\260\345\200\274\347\232\204\346\225\264\346\225\260\346\254\241\346\226\271.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23011\357\274\232\346\225\260\345\200\274\347\232\204\346\225\264\346\225\260\346\254\241\346\226\271.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23011\357\274\232\346\225\260\345\200\274\347\232\204\346\225\264\346\225\260\346\254\241\346\226\271.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23011\357\274\232\346\225\260\345\200\274\347\232\204\346\225\264\346\225\260\346\254\241\346\226\271.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23012\357\274\232\346\211\223\345\215\2601\345\210\260\346\234\200\345\244\247\347\232\204n\344\275\215\346\225\260.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23012\357\274\232\346\211\223\345\215\2601\345\210\260\346\234\200\345\244\247\347\232\204n\344\275\215\346\225\260.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23012\357\274\232\346\211\223\345\215\2601\345\210\260\346\234\200\345\244\247\347\232\204n\344\275\215\346\225\260.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23012\357\274\232\346\211\223\345\215\2601\345\210\260\346\234\200\345\244\247\347\232\204n\344\275\215\346\225\260.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23044\357\274\232\346\211\221\345\205\213\347\211\214\347\232\204\351\241\272\345\255\220.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23044\357\274\232\346\211\221\345\205\213\347\211\214\347\232\204\351\241\272\345\255\220.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23044\357\274\232\346\211\221\345\205\213\347\211\214\347\232\204\351\241\272\345\255\220.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23044\357\274\232\346\211\221\345\205\213\347\211\214\347\232\204\351\241\272\345\255\220.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23045\357\274\232\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23045\357\274\232\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23045\357\274\232\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\23045\357\274\232\345\234\206\345\234\210\344\270\255\346\234\200\345\220\216\345\211\251\344\270\213\347\232\204\346\225\260\345\255\227.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\2306\357\274\232\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\2306\357\274\232\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\2306\357\274\232\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\345\211\221\346\214\207Offer/\351\235\242\350\257\225\351\242\2306\357\274\232\351\207\215\345\273\272\344\272\214\345\217\211\346\240\221.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/1.\350\256\276\350\256\241\344\270\200\344\270\252\346\234\211getMin\345\212\237\350\203\275\347\232\204\346\240\210.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/1.\350\256\276\350\256\241\344\270\200\344\270\252\346\234\211getMin\345\212\237\350\203\275\347\232\204\346\240\210.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/1.\350\256\276\350\256\241\344\270\200\344\270\252\346\234\211getMin\345\212\237\350\203\275\347\232\204\346\240\210.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/1.\350\256\276\350\256\241\344\270\200\344\270\252\346\234\211getMin\345\212\237\350\203\275\347\232\204\346\240\210.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/2.\347\224\261\344\270\244\344\270\252\346\240\210\347\273\204\346\210\220\347\232\204\351\230\237\345\210\227.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/2.\347\224\261\344\270\244\344\270\252\346\240\210\347\273\204\346\210\220\347\232\204\351\230\237\345\210\227.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/2.\347\224\261\344\270\244\344\270\252\346\240\210\347\273\204\346\210\220\347\232\204\351\230\237\345\210\227.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/2.\347\224\261\344\270\244\344\270\252\346\240\210\347\273\204\346\210\220\347\232\204\351\230\237\345\210\227.md" diff --git "a/000 - 2 Data & Algorithm/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/3.\345\246\202\344\275\225\344\273\205\347\224\250\351\200\222\345\275\222\345\207\275\346\225\260\345\222\214\346\240\210\346\223\215\344\275\234\351\200\206\345\272\217\344\270\200\344\270\252\346\240\210.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/3.\345\246\202\344\275\225\344\273\205\347\224\250\351\200\222\345\275\222\345\207\275\346\225\260\345\222\214\346\240\210\346\223\215\344\275\234\351\200\206\345\272\217\344\270\200\344\270\252\346\240\210.md" similarity index 100% rename from "000 - 2 Data & Algorithm/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/3.\345\246\202\344\275\225\344\273\205\347\224\250\351\200\222\345\275\222\345\207\275\346\225\260\345\222\214\346\240\210\346\223\215\344\275\234\351\200\206\345\272\217\344\270\200\344\270\252\346\240\210.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Algorithm/\347\250\213\345\272\217\345\221\230\344\273\243\347\240\201\351\235\242\350\257\225\346\214\207\345\215\227(\345\267\246\347\250\213\344\272\221)/3.\345\246\202\344\275\225\344\273\205\347\224\250\351\200\222\345\275\222\345\207\275\346\225\260\345\222\214\346\240\210\346\223\215\344\275\234\351\200\206\345\272\217\344\270\200\344\270\252\346\240\210.md" diff --git a/000 - 2 Data & Algorithm/Btree.txt "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Btree.txt" similarity index 100% rename from 000 - 2 Data & Algorithm/Btree.txt rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/Btree.txt" diff --git "a/000 - 2 Data & Algorithm/DataStructure/B\346\240\221.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/B\346\240\221.md" similarity index 98% rename from "000 - 2 Data & Algorithm/DataStructure/B\346\240\221.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/B\346\240\221.md" index 01604c32..14947fd8 100644 --- "a/000 - 2 Data & Algorithm/DataStructure/B\346\240\221.md" +++ "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/B\346\240\221.md" @@ -1,66 +1,66 @@ -https://blog.csdn.net/v_JULY_v/article/details/6530142 - -外存储器 磁盘 - -磁盘的构造 - -磁盘是一个扁平的 **圆盘**(与电唱机的唱片类似)。 -盘面上有许多称为 **磁道** 的圆圈,数据就记录在这些磁道上。 -磁盘可以是单片的,也可以是由若干 **盘片** 组成的盘组,每一盘片上有 **两个面**。 -如下图11.3中所示的6片盘组为例,除去最顶端和最底端的外侧面不存储数据之外,一共有10个面可以用来保存信息。 - - - -当磁盘驱动器执行读/写功能时。盘片装在一个主轴上,并绕主轴高速旋转,当磁道在读/写头(又叫磁头) 下通过时,就可以进行数据的读 / 写了。 - -一般磁盘分为固定头盘(磁头固定)和活动头盘。固定头盘的每一个磁道上都有独立的磁头,它是固定不动的,专门负责这一磁道上数据的读/写。 - -活动头盘 (如上图)的磁头是可移动的。每一个盘面上只有一个磁头(磁头是双向的,因此正反盘面都能读写)。它可以从该面的一个磁道移动到另一个磁道。所有磁头都装在同一个动臂上,因此不同盘面上的所有磁头都是同时移动的(行动整齐划一)。当盘片绕主轴旋转的时候,磁头与旋转的盘片形成一个圆柱体。各个盘面上半径相同的磁道组成了一个圆柱面,我们称为柱面 。因此,柱面的个数也就是盘面上的磁道数。 - - -2.2磁盘的读/写原理和效率 - -磁盘上数据必须用一个三维地址唯一标示:柱面号、盘面号、块号(磁道上的盘块)。 - -读/写磁盘上某一指定数据需要下面3个步骤: - -(1) 首先移动臂根据柱面号使磁头移动到所需要的柱面上,这一过程被称为定位或查找 。 - -(2) 如上图11.3中所示的6盘组示意图中,所有磁头都定位到了10个盘面的10条磁道上(磁头都是双向的)。这时根据盘面号来确定指定盘面上的磁道。 - -(3) 盘面确定以后,盘片开始旋转,将指定块号的磁道段移动至磁头下。 - -经过上面三个步骤,指定数据的存储位置就被找到。这时就可以开始读/写操作了。 - -访问某一具体信息,由3部分时间组成: - -● 查找时间(seek time) Ts: 完成上述步骤(1)所需要的时间。这部分时间代价最高,最大可达到0.1s左右。 - -● 等待时间(latency time) Tl: 完成上述步骤(3)所需要的时间。由于盘片绕主轴旋转速度很快,一般为7200转/分(电脑硬盘的性能指标之一, 家用的普通硬盘的转速一般有5400rpm(笔记本)、7200rpm几种)。因此一般旋转一圈大约0.0083s。 - -● 传输时间(transmission time) Tt: 数据通过系统总线传送到内存的时间,一般传输一个字节(byte)大概0.02us=2*10^(-8)s - -磁盘读取数据是以盘块(block)为基本单位的。位于同一盘块中的所有数据都能被一次性全部读取出来。而磁盘IO代价主要花费在查找时间Ts上。因此我们应该尽量将相关信息存放在同一盘块,同一磁道中。或者至少放在同一柱面或相邻柱面上,以求在读/写信息时尽量减少磁头来回移动的次数,避免过多的查找时间Ts。 - -所以,在大规模数据存储方面,大量数据存储在外存磁盘中,而在外存磁盘中读取/写入块(block)中某数据时,首先需要定位到磁盘中的某块,如何有效地查找磁盘中的数据,需要一种合理高效的外存数据结构,就是下面所要重点阐述的B-tree结构 - - -## B树 - B树 就是 B-Tree B 树又叫平衡多路查找树 - - B树与红黑树最大的不同在于,B树的结点可以有许多子女,从几个到几千个。那为什么又说B树与红黑树很相似呢? - 因为与红黑树一样,一棵含n个结点的B树的高度也为O(lgn),但可能比一棵红黑树的高度小许多,应为它的分支因子比较大。所以,B树可以在O(logn)时间内,实现各种如插入(insert),删除(delete)等动态集合操作。 - - 一个内结点x若含有n[x]个关键字,那么x将含有n[x]+1个子女。 - - B树的类型 - keyNum 关键字个数 - parent 指向父结点 - *ptr 子树指针向量 - *key 关键字向量* - - B-树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点;所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中; - - B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中; - - B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3; +https://blog.csdn.net/v_JULY_v/article/details/6530142 + +外存储器 磁盘 + +磁盘的构造 + +磁盘是一个扁平的 **圆盘**(与电唱机的唱片类似)。 +盘面上有许多称为 **磁道** 的圆圈,数据就记录在这些磁道上。 +磁盘可以是单片的,也可以是由若干 **盘片** 组成的盘组,每一盘片上有 **两个面**。 +如下图11.3中所示的6片盘组为例,除去最顶端和最底端的外侧面不存储数据之外,一共有10个面可以用来保存信息。 + + + +当磁盘驱动器执行读/写功能时。盘片装在一个主轴上,并绕主轴高速旋转,当磁道在读/写头(又叫磁头) 下通过时,就可以进行数据的读 / 写了。 + +一般磁盘分为固定头盘(磁头固定)和活动头盘。固定头盘的每一个磁道上都有独立的磁头,它是固定不动的,专门负责这一磁道上数据的读/写。 + +活动头盘 (如上图)的磁头是可移动的。每一个盘面上只有一个磁头(磁头是双向的,因此正反盘面都能读写)。它可以从该面的一个磁道移动到另一个磁道。所有磁头都装在同一个动臂上,因此不同盘面上的所有磁头都是同时移动的(行动整齐划一)。当盘片绕主轴旋转的时候,磁头与旋转的盘片形成一个圆柱体。各个盘面上半径相同的磁道组成了一个圆柱面,我们称为柱面 。因此,柱面的个数也就是盘面上的磁道数。 + + +2.2磁盘的读/写原理和效率 + +磁盘上数据必须用一个三维地址唯一标示:柱面号、盘面号、块号(磁道上的盘块)。 + +读/写磁盘上某一指定数据需要下面3个步骤: + +(1) 首先移动臂根据柱面号使磁头移动到所需要的柱面上,这一过程被称为定位或查找 。 + +(2) 如上图11.3中所示的6盘组示意图中,所有磁头都定位到了10个盘面的10条磁道上(磁头都是双向的)。这时根据盘面号来确定指定盘面上的磁道。 + +(3) 盘面确定以后,盘片开始旋转,将指定块号的磁道段移动至磁头下。 + +经过上面三个步骤,指定数据的存储位置就被找到。这时就可以开始读/写操作了。 + +访问某一具体信息,由3部分时间组成: + +● 查找时间(seek time) Ts: 完成上述步骤(1)所需要的时间。这部分时间代价最高,最大可达到0.1s左右。 + +● 等待时间(latency time) Tl: 完成上述步骤(3)所需要的时间。由于盘片绕主轴旋转速度很快,一般为7200转/分(电脑硬盘的性能指标之一, 家用的普通硬盘的转速一般有5400rpm(笔记本)、7200rpm几种)。因此一般旋转一圈大约0.0083s。 + +● 传输时间(transmission time) Tt: 数据通过系统总线传送到内存的时间,一般传输一个字节(byte)大概0.02us=2*10^(-8)s + +磁盘读取数据是以盘块(block)为基本单位的。位于同一盘块中的所有数据都能被一次性全部读取出来。而磁盘IO代价主要花费在查找时间Ts上。因此我们应该尽量将相关信息存放在同一盘块,同一磁道中。或者至少放在同一柱面或相邻柱面上,以求在读/写信息时尽量减少磁头来回移动的次数,避免过多的查找时间Ts。 + +所以,在大规模数据存储方面,大量数据存储在外存磁盘中,而在外存磁盘中读取/写入块(block)中某数据时,首先需要定位到磁盘中的某块,如何有效地查找磁盘中的数据,需要一种合理高效的外存数据结构,就是下面所要重点阐述的B-tree结构 + + +## B树 + B树 就是 B-Tree B 树又叫平衡多路查找树 + + B树与红黑树最大的不同在于,B树的结点可以有许多子女,从几个到几千个。那为什么又说B树与红黑树很相似呢? + 因为与红黑树一样,一棵含n个结点的B树的高度也为O(lgn),但可能比一棵红黑树的高度小许多,应为它的分支因子比较大。所以,B树可以在O(logn)时间内,实现各种如插入(insert),删除(delete)等动态集合操作。 + + 一个内结点x若含有n[x]个关键字,那么x将含有n[x]+1个子女。 + + B树的类型 + keyNum 关键字个数 + parent 指向父结点 + *ptr 子树指针向量 + *key 关键字向量* + + B-树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点;所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中; + + B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中; + + B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3; diff --git a/000 - 2 Data & Algorithm/DataStructure/all.md "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/all.md" similarity index 100% rename from 000 - 2 Data & Algorithm/DataStructure/all.md rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/all.md" diff --git "a/000 - 2 Data & Algorithm/DataStructure/\346\225\260\346\215\256\347\273\223\346\236\204(Java).md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\346\225\260\346\215\256\347\273\223\346\236\204(Java).md" similarity index 97% rename from "000 - 2 Data & Algorithm/DataStructure/\346\225\260\346\215\256\347\273\223\346\236\204(Java).md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\346\225\260\346\215\256\347\273\223\346\236\204(Java).md" index a9736ad4..34b5c39b 100644 --- "a/000 - 2 Data & Algorithm/DataStructure/\346\225\260\346\215\256\347\273\223\346\236\204(Java).md" +++ "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\346\225\260\346\215\256\347\273\223\346\236\204(Java).md" @@ -8,35 +8,35 @@ 创建 -``` +```java int c[] = {2,3,6,10,99}; int[] d = new int[10]; ``` -``` +```java /** * 数组检索 * @param args */ public static void main(String[] args) { String name[]; - + name = new String[5]; name[0] = "egg"; name[1] = "erqing"; name[2] = "baby"; - + for(int i = 0; i < name.length; i++){ System.out.println(name[i]); } } ``` -``` +```java /** * 插入 - * + * * @param old * @param value * @param index @@ -51,7 +51,7 @@ int[] d = new int[10]; /** * 遍历 - * + * * @param data */ public static void traverse(int data[]) { @@ -62,7 +62,7 @@ int[] d = new int[10]; /** * 删除 - * + * * @param old * @param index * @return @@ -119,4 +119,4 @@ Tips:数组中删除和增加元素的原理:增加元素,需要将index后 **动态规划、贪心算法、分治算法。(一般不会问到)** -**大数据处理:类似10亿条数据找出最大的1000个数.........等等** \ No newline at end of file +**大数据处理:类似10亿条数据找出最大的1000个数.........等等** diff --git "a/000 - 2 Data & Algorithm/DataStructure/\346\225\260\347\273\204.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\346\225\260\347\273\204.md" similarity index 98% rename from "000 - 2 Data & Algorithm/DataStructure/\346\225\260\347\273\204.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\346\225\260\347\273\204.md" index b83f81ae..298adce0 100644 --- "a/000 - 2 Data & Algorithm/DataStructure/\346\225\260\347\273\204.md" +++ "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\346\225\260\347\273\204.md" @@ -1,7 +1,7 @@ #数组 --- -``` +```java /** * 普通数组的Java代码 * @author dream @@ -12,13 +12,13 @@ public class GeneralArray { private int[] a; private int size; //数组的大小 private int nElem; //数组中有多少项 - + public GeneralArray(int max){ this.a = new int[max]; this.size = max; this.nElem = 0; } - + public boolean find(int searchNum){ //查找某个值 int j; for(j = 0; j < nElem; j++){ @@ -32,8 +32,8 @@ public class GeneralArray { return true; } } - - + + public boolean insert(int value){ //插入某个值 if(nElem == size){ System.out.println("数组已满"); @@ -43,7 +43,7 @@ public class GeneralArray { nElem++; return true; } - + public boolean delete(int value){ //删除某个值 int j; for(j = 0; j < nElem; j++){ @@ -66,7 +66,7 @@ public class GeneralArray { nElem--; return true; } - + public void display(){ //打印整个数组 for(int i = 0; i < nElem; i++){ System.out.println(a[i] + " "); @@ -77,7 +77,7 @@ public class GeneralArray { ``` -``` +```java /** * 有序数组的Java代码 * @author dream @@ -99,17 +99,17 @@ public class OrderedArray { private long[] a; private int size; //数组的大小 private int nElem; //数组中有多少项 - + public OrderedArray(int max){ //初始化数组 this.a = new long[max]; this.size = max; this.nElem = 0; } - + public int size(){ //返回数组实际有多少值 return this.nElem; } - + /** * 二分查找 * @param searchNum @@ -134,8 +134,8 @@ public class OrderedArray { } } } - - + + public boolean insert(long value){ //插入某个值 if(nElem == size){ System.out.println("数组已满!"); @@ -147,7 +147,7 @@ public class OrderedArray { break; } } - + for(int k = nElem; k > j; k++){ a[k] = a[k-1]; } @@ -155,16 +155,16 @@ public class OrderedArray { nElem++; return true; } - - - + + + public boolean delete(long value){ //删除某个值 int j = find(value); if(j == -1){ System.out.println("没有该元素!"); return false; } - + if(nElem == size){ for(int k = j; k < nElem - 1; k++){ a[k] = a[k+1]; @@ -178,8 +178,8 @@ public class OrderedArray { nElem--; return true; } - - + + public void display(){ //打印整个数组 for(int i = 0; i < nElem; i++){ System.out.println(a[i] + " "); @@ -188,4 +188,4 @@ public class OrderedArray { } } -``` \ No newline at end of file +``` diff --git "a/000 - 2 Data & Algorithm/DataStructure/\346\240\210\345\222\214\351\230\237\345\210\227.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\346\240\210\345\222\214\351\230\237\345\210\227.md" similarity index 97% rename from "000 - 2 Data & Algorithm/DataStructure/\346\240\210\345\222\214\351\230\237\345\210\227.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\346\240\210\345\222\214\351\230\237\345\210\227.md" index 2847248d..f541bd7b 100644 --- "a/000 - 2 Data & Algorithm/DataStructure/\346\240\210\345\222\214\351\230\237\345\210\227.md" +++ "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\346\240\210\345\222\214\351\230\237\345\210\227.md" @@ -7,7 +7,7 @@ 栈最基本的操作是出栈(Pop)、入栈(Push),还有其他扩展操作,如查看栈顶元素,判断栈是否为空、是否已满,读取栈的大小等。 -``` +```java /** * 栈是先进后出 * 只能访问栈顶的数据 @@ -26,13 +26,13 @@ public class ArrayStack { private long[] a; private int size; //栈数组的大小 private int top; //栈顶 - + public ArrayStack(int maxSize){ this.size = maxSize; this.a = new long[size]; this.top = -1; //表示空栈 } - + public void push(long value){ //入栈 if(isFull()){ System.out.println("栈已满!"); @@ -40,7 +40,7 @@ public class ArrayStack { } a[++top] = value; } - + public long peek(){ //返回栈顶内容,但不删除 if(isEmpty()){ System.out.println("栈中没有数据"); @@ -48,8 +48,8 @@ public class ArrayStack { } return a[top]; } - - + + public long pop(){ //弹出栈顶内容 if(isEmpty()){ System.out.println("栈中没有数据!"); @@ -57,11 +57,11 @@ public class ArrayStack { } return a[top--]; } - + public int size(){ return top + 1; } - + /** * 判断是否满了 * @return @@ -69,7 +69,7 @@ public class ArrayStack { public boolean isFull(){ return (top == size - 1); } - + /** * 是否为空 * @return @@ -77,15 +77,15 @@ public class ArrayStack { public boolean isEmpty(){ return (top == -1); } - - + + public void display(){ for (int i = top; i >= 0; i--) { System.out.println(a[i] + " "); } System.out.println(""); } - + } ``` @@ -95,7 +95,7 @@ public class ArrayStack { 依然使用数组作为底层容器来实现一个队列的封装 -``` +```java /** * 队列也可以用数组来实现,不过这里有个问题,当数组下标满了后就不能再添加了, * 但是数组前面由于已经删除队列头的数据了,导致空。所以队列我们可以用循环数组来实现, @@ -109,7 +109,7 @@ public class RoundQueue { private int nItems; //实际存储数量 private int front; //头 private int rear; //尾 - + public RoundQueue(int maxSize){ this.size = maxSize; a = new long[size]; @@ -117,7 +117,7 @@ public class RoundQueue { rear = -1; nItems = 0; } - + public void insert(long value){ if(isFull()){ System.out.println("队列已满"); @@ -127,7 +127,7 @@ public class RoundQueue { a[rear] = value; //尾指针满了就循环到0处,这句相当于下面注释内容 nItems++; } - + public long remove(){ if(isEmpty()){ System.out.println("队列为空!"); @@ -137,7 +137,7 @@ public class RoundQueue { front = front % size; return a[front++]; } - + public void display(){ if(isEmpty()){ System.out.println("队列为空!"); @@ -149,7 +149,7 @@ public class RoundQueue { } System.out.println(""); } - + public long peek(){ if(isEmpty()){ System.out.println("队列为空!"); @@ -157,20 +157,20 @@ public class RoundQueue { } return a[front]; } - + public boolean isFull(){ return (nItems == size); } - + public boolean isEmpty(){ return (nItems == 0); } - + public int size(){ return nItems; } - - + + } ``` @@ -178,21 +178,21 @@ public class RoundQueue { 和栈一样,队列中插入数据项和删除数据项的时间复杂度均为O(1) 还有个优先级队列,优先级队列是比栈和队列更专用的数据结构。优先级队列与上面普通的队列相比,主要区别在于队列中的元素是有序的,关键字最小(或者最大)的数据项总在队头。数据项插入的时候会按照顺序插入到合适的位置以确保队列的顺序。优先级队列的内部实现可以用数组或者一种特别的树——堆来实现。这里用数组实现优先级队列。 - - ``` - + + ```java + public class PriorityQueue { private long[] a; private int size; private int nItems; //元素个数 - + public PriorityQueue(int maxSize){ size = maxSize; nItems = 0; a = new long[size]; } - + public void insert(long value){ if(isFull()){ System.out.println("队列已满!"); @@ -209,13 +209,13 @@ public class PriorityQueue { } else { break; - } + } } a[j+1] = value; nItems++; } } - + public long remove(){ if(isFull()){ System.out.println("队列为空!"); @@ -223,23 +223,23 @@ public class PriorityQueue { } return a[--nItems]; } - + public long peekMin(){ return a[nItems - 1]; } - + public boolean isFull(){ return (nItems == size); } - + public boolean isEmpty(){ return (nItems == 0); } - + public int size(){ return nItems; } - + public void display(){ for(int i = nItems - 1;i >= 0; i--){ System.out.println(a[i] + " "); @@ -249,9 +249,5 @@ public class PriorityQueue { } ``` - - 优先级队列中,插入操作需要O(N)的时间,而删除操作则需要O(1)的时间。 - - - + 优先级队列中,插入操作需要O(N)的时间,而删除操作则需要O(1)的时间。 diff --git "a/000 - 2 Data & Algorithm/DataStructure/\351\200\222\345\275\222\345\222\214\351\235\236\351\200\222\345\275\222\346\226\271\345\274\217\345\256\236\347\216\260\344\272\214\345\217\211\346\240\221\345\205\210\343\200\201\344\270\255\343\200\201\345\220\216\345\272\217\351\201\215\345\216\206.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\351\200\222\345\275\222\345\222\214\351\235\236\351\200\222\345\275\222\346\226\271\345\274\217\345\256\236\347\216\260\344\272\214\345\217\211\346\240\221\345\205\210\343\200\201\344\270\255\343\200\201\345\220\216\345\272\217\351\201\215\345\216\206.md" similarity index 98% rename from "000 - 2 Data & Algorithm/DataStructure/\351\200\222\345\275\222\345\222\214\351\235\236\351\200\222\345\275\222\346\226\271\345\274\217\345\256\236\347\216\260\344\272\214\345\217\211\346\240\221\345\205\210\343\200\201\344\270\255\343\200\201\345\220\216\345\272\217\351\201\215\345\216\206.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\351\200\222\345\275\222\345\222\214\351\235\236\351\200\222\345\275\222\346\226\271\345\274\217\345\256\236\347\216\260\344\272\214\345\217\211\346\240\221\345\205\210\343\200\201\344\270\255\343\200\201\345\220\216\345\272\217\351\201\215\345\216\206.md" index 20ea8852..e657934e 100644 --- "a/000 - 2 Data & Algorithm/DataStructure/\351\200\222\345\275\222\345\222\214\351\235\236\351\200\222\345\275\222\346\226\271\345\274\217\345\256\236\347\216\260\344\272\214\345\217\211\346\240\221\345\205\210\343\200\201\344\270\255\343\200\201\345\220\216\345\272\217\351\201\215\345\216\206.md" +++ "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/DataStructure/\351\200\222\345\275\222\345\222\214\351\235\236\351\200\222\345\275\222\346\226\271\345\274\217\345\256\236\347\216\260\344\272\214\345\217\211\346\240\221\345\205\210\343\200\201\344\270\255\343\200\201\345\220\216\345\272\217\351\201\215\345\216\206.md" @@ -5,20 +5,20 @@ 递归实现: -``` +```java public class Node { public int value; public Node left; public Node right; - + public Node(int data){ this.value = data; } } ``` -``` +```java /** * 前序遍历 * @param head @@ -31,7 +31,7 @@ public class Node { preOrderRecur(head.left); preOrderRecur(head.right); } - + /** * 中序遍历 * @param head @@ -44,7 +44,7 @@ public class Node { System.out.println(head.value + " "); inOderRecur(head.right); } - + /** * 后序遍历 * @param head @@ -62,4 +62,3 @@ public class Node { 非递归遍历 - diff --git a/000 - 2 Data & Algorithm/HashMap.md "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/HashMap.md" similarity index 100% rename from 000 - 2 Data & Algorithm/HashMap.md rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/HashMap.md" diff --git a/000 - 2 Data & Algorithm/img/rbt1.png "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/img/rbt1.png" similarity index 100% rename from 000 - 2 Data & Algorithm/img/rbt1.png rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/img/rbt1.png" diff --git a/000 - 2 Data & Algorithm/img/rbt2.png "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/img/rbt2.png" similarity index 100% rename from 000 - 2 Data & Algorithm/img/rbt2.png rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/img/rbt2.png" diff --git "a/000 - 2 Data & Algorithm/\345\211\221\346\214\207offer.txt" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\345\211\221\346\214\207offer.txt" similarity index 100% rename from "000 - 2 Data & Algorithm/\345\211\221\346\214\207offer.txt" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\345\211\221\346\214\207offer.txt" diff --git "a/000 - 2 Data & Algorithm/\345\212\250\346\200\201\350\247\204\345\210\222.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" similarity index 100% rename from "000 - 2 Data & Algorithm/\345\212\250\346\200\201\350\247\204\345\210\222.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\345\212\250\346\200\201\350\247\204\345\210\222.md" diff --git "a/000 - 2 Data & Algorithm/\345\246\202\344\275\225\345\210\244\346\226\255\351\223\276\350\241\250\346\234\211\347\216\257.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\345\246\202\344\275\225\345\210\244\346\226\255\351\223\276\350\241\250\346\234\211\347\216\257.md" similarity index 100% rename from "000 - 2 Data & Algorithm/\345\246\202\344\275\225\345\210\244\346\226\255\351\223\276\350\241\250\346\234\211\347\216\257.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\345\246\202\344\275\225\345\210\244\346\226\255\351\223\276\350\241\250\346\234\211\347\216\257.md" diff --git "a/000 - 2 Data & Algorithm/\346\211\276\345\207\272\347\274\272\345\244\261\347\232\204\346\225\264\346\225\260.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\346\211\276\345\207\272\347\274\272\345\244\261\347\232\204\346\225\264\346\225\260.md" similarity index 100% rename from "000 - 2 Data & Algorithm/\346\211\276\345\207\272\347\274\272\345\244\261\347\232\204\346\225\264\346\225\260.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\346\211\276\345\207\272\347\274\272\345\244\261\347\232\204\346\225\264\346\225\260.md" diff --git "a/000 - 2 Data & Algorithm/\346\234\200\345\260\217\346\240\210\347\232\204\345\256\236\347\216\260.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\346\234\200\345\260\217\346\240\210\347\232\204\345\256\236\347\216\260.md" similarity index 100% rename from "000 - 2 Data & Algorithm/\346\234\200\345\260\217\346\240\210\347\232\204\345\256\236\347\216\260.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\346\234\200\345\260\217\346\240\210\347\232\204\345\256\236\347\216\260.md" diff --git "a/000 - 2 Data & Algorithm/\347\250\213\345\272\217\345\221\230\345\277\205\351\241\273\347\237\245\351\201\223\347\232\20410\345\244\247\345\237\272\347\241\200\345\256\236\347\224\250\347\256\227\346\263\225\345\217\212\345\205\266\350\256\262\350\247\243.txt" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\347\250\213\345\272\217\345\221\230\345\277\205\351\241\273\347\237\245\351\201\223\347\232\20410\345\244\247\345\237\272\347\241\200\345\256\236\347\224\250\347\256\227\346\263\225\345\217\212\345\205\266\350\256\262\350\247\243.txt" similarity index 100% rename from "000 - 2 Data & Algorithm/\347\250\213\345\272\217\345\221\230\345\277\205\351\241\273\347\237\245\351\201\223\347\232\20410\345\244\247\345\237\272\347\241\200\345\256\236\347\224\250\347\256\227\346\263\225\345\217\212\345\205\266\350\256\262\350\247\243.txt" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\347\250\213\345\272\217\345\221\230\345\277\205\351\241\273\347\237\245\351\201\223\347\232\20410\345\244\247\345\237\272\347\241\200\345\256\236\347\224\250\347\256\227\346\263\225\345\217\212\345\205\266\350\256\262\350\247\243.txt" diff --git "a/000 - 2 Data & Algorithm/\347\272\242\351\273\221\346\240\221.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\347\272\242\351\273\221\346\240\221.md" similarity index 100% rename from "000 - 2 Data & Algorithm/\347\272\242\351\273\221\346\240\221.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\347\272\242\351\273\221\346\240\221.md" diff --git "a/000 - 2 Data & Algorithm/\350\276\227\350\275\254\347\233\270\351\231\244\346\263\225.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\350\276\227\350\275\254\347\233\270\351\231\244\346\263\225.md" similarity index 100% rename from "000 - 2 Data & Algorithm/\350\276\227\350\275\254\347\233\270\351\231\244\346\263\225.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\350\276\227\350\275\254\347\233\270\351\231\244\346\263\225.md" diff --git "a/000 - 2 Data & Algorithm/\351\253\230\345\271\266\345\217\221\344\270\213\347\232\204HashMap.md" "b/000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\351\253\230\345\271\266\345\217\221\344\270\213\347\232\204HashMap.md" similarity index 100% rename from "000 - 2 Data & Algorithm/\351\253\230\345\271\266\345\217\221\344\270\213\347\232\204HashMap.md" rename to "000 - 2 Data & Algorithm \346\225\260\346\215\256\347\273\223\346\236\204&\347\256\227\346\263\225/\351\253\230\345\271\266\345\217\221\344\270\213\347\232\204HashMap.md" diff --git "a/000 - 3 Design Patterns/Builder\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/Builder\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/Builder\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/Builder\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/JDK\344\270\255\347\232\204\350\256\276\350\256\241\346\250\241\345\274\217.md" diff --git a/000 - 3 Design Patterns/all.md "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/all.md" similarity index 98% rename from 000 - 3 Design Patterns/all.md rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/all.md" index 7f65b313..d597e696 100644 --- a/000 - 3 Design Patterns/all.md +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/all.md" @@ -1,13 +1,13 @@ -**工厂方法模式**:适合 出现了大量的产品需要创建,并且有公共的接口,可以通过工厂方法模式进行创建,一个工厂里,不同方法创建不同的类。 - -**抽象工厂** :工厂方法模式有一个问题就是类的创建依赖于工厂,也就是说想要扩展程序,必须对工厂类进行修改,用抽象工厂,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不用改以前的代码,一个工厂生产一个具体对象 - -**建造者模式**:工厂模式提供的是创建单个对象的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象。 - -**原型模式**:讲一个对象作为原型,对其进行赋值克隆,产生一个和元对象类似的新对象。 - -**适配器模式**:将某个类的接口转换为客户端期望的另一个接口表示。 - -**外观模式 facade**:为了解决类与类之间的依赖关系,将他们的关系放在facade类中。 - -**组合模式**:在处理类似树形结构的问题时很方便。 +**工厂方法模式**:适合 出现了大量的产品需要创建,并且有公共的接口,可以通过工厂方法模式进行创建,一个工厂里,不同方法创建不同的类。 + +**抽象工厂** :工厂方法模式有一个问题就是类的创建依赖于工厂,也就是说想要扩展程序,必须对工厂类进行修改,用抽象工厂,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不用改以前的代码,一个工厂生产一个具体对象 + +**建造者模式**:工厂模式提供的是创建单个对象的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象。 + +**原型模式**:讲一个对象作为原型,对其进行赋值克隆,产生一个和元对象类似的新对象。 + +**适配器模式**:将某个类的接口转换为客户端期望的另一个接口表示。 + +**外观模式 facade**:为了解决类与类之间的依赖关系,将他们的关系放在facade类中。 + +**组合模式**:在处理类似树形结构的问题时很方便。 diff --git "a/000 - 3 Design Patterns/\344\273\243\347\220\206\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\344\273\243\347\220\206\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\344\273\243\347\220\206\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\344\273\243\347\220\206\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\345\215\225\344\276\213\344\270\203\347\247\215\345\206\231\346\263\225.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\344\270\203\347\247\215\345\206\231\346\263\225.md" similarity index 100% rename from "000 - 3 Design Patterns/\345\215\225\344\276\213\344\270\203\347\247\215\345\206\231\346\263\225.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\344\270\203\347\247\215\345\206\231\346\263\225.md" diff --git "a/000 - 3 Design Patterns/\345\215\225\344\276\213\346\250\241\345\274\217 \346\207\222\346\261\211 \345\217\214\351\207\215\346\243\200\346\265\213\346\234\272\345\210\266.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217 \346\207\222\346\261\211 \345\217\214\351\207\215\346\243\200\346\265\213\346\234\272\345\210\266.md" similarity index 97% rename from "000 - 3 Design Patterns/\345\215\225\344\276\213\346\250\241\345\274\217 \346\207\222\346\261\211 \345\217\214\351\207\215\346\243\200\346\265\213\346\234\272\345\210\266.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217 \346\207\222\346\261\211 \345\217\214\351\207\215\346\243\200\346\265\213\346\234\272\345\210\266.md" index 593b3207..ab875033 100644 --- "a/000 - 3 Design Patterns/\345\215\225\344\276\213\346\250\241\345\274\217 \346\207\222\346\261\211 \345\217\214\351\207\215\346\243\200\346\265\213\346\234\272\345\210\266.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217 \346\207\222\346\261\211 \345\217\214\351\207\215\346\243\200\346\265\213\346\234\272\345\210\266.md" @@ -1,67 +1,67 @@ -``` java -public class Singleton { - private Singleton() {} //私有构造函数 - private static Singleton instance = null; //单例对象 - //静态工厂方法 - public static Singleton getInstance() { - if (instance == null) { - instance = new Singleton(); - } - return instance; - } -} -``` -两个线程同时进入 `instance = new Singleton();` 则会构建了两次 - -```java -public class Singleton { - private Singleton() {} //私有构造函数 - private static Singleton instance = null; //单例对象 - //静态工厂方法 - public static Singleton getInstance() { - if (instance == null) { //双重检测机制 - synchronized (Singleton.class){ //同步锁 - if (instance == null) { //双重检测机制 - instance = new Singleton(); - } - } - } - return instance; - } -} -``` -* 防止new Singleton() 被执行多次 -* 进入Synchronized 临界区以后,还要再做一次判空。因为当两个线程同时访问的时候,线程A构建完对象,线程B也已经通过了最初的判空验证,不做第二次判空的话,线程B还是会再次构建instance对象。 - -重排序, -instance = new Singleton,会被编译器编译成如下JVM指令: - -memory =allocate(); // **1:分配对象的内存空间** -ctorInstance(memory); // **2:初始化对象** -instance =memory; // **3:设置instance指向刚分配的内存地址** -但是这些指令顺序并非一成不变,有可能会经过JVM和CPU的优化,指令重排成下面的顺序: -memory =allocate(); // **1:分配对象的内存空间** -instance =memory; // **3:设置instance指向刚分配的内存地址** -ctorInstance(memory); // **2:初始化对象** - -当线程A执行完1,3,时,instance对象还未完成初始化,但已经不再指向null。 -此时如果线程B抢占到CPU资源,执行 if(instance == null)的结果会是false,从而返回一个没有初始化完成的instance对象。 - -``` java -public class Singleton { - private Singleton() {} //私有构造函数 - private **volatile** static Singleton instance = null; //单例对象 - //静态工厂方法 - public static Singleton getInstance() { - if (instance == null) { //双重检测机制 - synchronized (Singleton.class){ //同步锁 - if (instance == null) { //双重检测机制 - instance = new Singleton(); - } - } - } - return instance; - } -} -``` -* volatile 禁止了重排序,避免了前面的问题。 +``` java +public class Singleton { + private Singleton() {} //私有构造函数 + private static Singleton instance = null; //单例对象 + //静态工厂方法 + public static Singleton getInstance() { + if (instance == null) { + instance = new Singleton(); + } + return instance; + } +} +``` +两个线程同时进入 `instance = new Singleton();` 则会构建了两次 + +```java +public class Singleton { + private Singleton() {} //私有构造函数 + private static Singleton instance = null; //单例对象 + //静态工厂方法 + public static Singleton getInstance() { + if (instance == null) { //双重检测机制 + synchronized (Singleton.class){ //同步锁 + if (instance == null) { //双重检测机制 + instance = new Singleton(); + } + } + } + return instance; + } +} +``` +* 防止new Singleton() 被执行多次 +* 进入Synchronized 临界区以后,还要再做一次判空。因为当两个线程同时访问的时候,线程A构建完对象,线程B也已经通过了最初的判空验证,不做第二次判空的话,线程B还是会再次构建instance对象。 + +重排序, +instance = new Singleton,会被编译器编译成如下JVM指令: + +memory =allocate(); // **1:分配对象的内存空间** +ctorInstance(memory); // **2:初始化对象** +instance =memory; // **3:设置instance指向刚分配的内存地址** +但是这些指令顺序并非一成不变,有可能会经过JVM和CPU的优化,指令重排成下面的顺序: +memory =allocate(); // **1:分配对象的内存空间** +instance =memory; // **3:设置instance指向刚分配的内存地址** +ctorInstance(memory); // **2:初始化对象** + +当线程A执行完1,3,时,instance对象还未完成初始化,但已经不再指向null。 +此时如果线程B抢占到CPU资源,执行 if(instance == null)的结果会是false,从而返回一个没有初始化完成的instance对象。 + +``` java +public class Singleton { + private Singleton() {} //私有构造函数 + private **volatile** static Singleton instance = null; //单例对象 + //静态工厂方法 + public static Singleton getInstance() { + if (instance == null) { //双重检测机制 + synchronized (Singleton.class){ //同步锁 + if (instance == null) { //双重检测机制 + instance = new Singleton(); + } + } + } + return instance; + } +} +``` +* volatile 禁止了重排序,避免了前面的问题。 diff --git "a/000 - 3 Design Patterns/\345\215\225\344\276\213\346\250\241\345\274\217 \350\241\215\347\224\237.txt" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217 \350\241\215\347\224\237.txt" similarity index 100% rename from "000 - 3 Design Patterns/\345\215\225\344\276\213\346\250\241\345\274\217 \350\241\215\347\224\237.txt" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217 \350\241\215\347\224\237.txt" diff --git "a/000 - 3 Design Patterns/\345\215\225\344\276\213\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\345\215\225\344\276\213\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\345\215\225\344\276\213\346\250\241\345\274\2172.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\2172.md" similarity index 100% rename from "000 - 3 Design Patterns/\345\215\225\344\276\213\346\250\241\345\274\2172.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\2172.md" diff --git "a/000 - 3 Design Patterns/\345\216\237\345\236\213\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\216\237\345\236\213\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\345\216\237\345\236\213\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\216\237\345\236\213\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\345\244\226\350\247\202\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\244\226\350\247\202\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\345\244\226\350\247\202\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\244\226\350\247\202\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\345\270\270\350\247\201\347\232\204\351\235\242\345\220\221\345\257\271\350\261\241\350\256\276\350\256\241\345\216\237\345\210\231.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\270\270\350\247\201\347\232\204\351\235\242\345\220\221\345\257\271\350\261\241\350\256\276\350\256\241\345\216\237\345\210\231.md" similarity index 100% rename from "000 - 3 Design Patterns/\345\270\270\350\247\201\347\232\204\351\235\242\345\220\221\345\257\271\350\261\241\350\256\276\350\256\241\345\216\237\345\210\231.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\345\270\270\350\247\201\347\232\204\351\235\242\345\220\221\345\257\271\350\261\241\350\256\276\350\256\241\345\216\237\345\210\231.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01 \345\210\233\345\273\272\345\236\213\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01 \345\210\233\345\273\272\345\236\213\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01 \345\210\233\345\273\272\345\236\213\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01 \345\210\233\345\273\272\345\236\213\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-01 - \347\256\200\345\215\225\345\267\245\345\216\202\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-01 - \347\256\200\345\215\225\345\267\245\345\216\202\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-01 - \347\256\200\345\215\225\345\267\245\345\216\202\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-01 - \347\256\200\345\215\225\345\267\245\345\216\202\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-02 - \345\267\245\345\216\202\346\226\271\346\263\225\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-02 - \345\267\245\345\216\202\346\226\271\346\263\225\346\250\241\345\274\217.md" similarity index 99% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-02 - \345\267\245\345\216\202\346\226\271\346\263\225\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-02 - \345\267\245\345\216\202\346\226\271\346\263\225\346\250\241\345\274\217.md" index 491b324e..23221cac 100644 --- "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-02 - \345\267\245\345\216\202\346\226\271\346\263\225\346\250\241\345\274\217.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-02 - \345\267\245\345\216\202\346\226\271\346\263\225\346\250\241\345\274\217.md" @@ -1,51 +1,51 @@ -## 2.1. 模式动机 -现在对该系统进行修改,不再设计一个按钮工厂类来统一负责所有产品的创建,而是将具体按钮的创建过程交给专门的工厂子类去完成,我们先定义一个 **抽象的按钮工厂类**,再定义 **具体的工厂类** 来生成 **圆形按钮、矩形按钮、菱形按钮** 等,它们实现在抽象按钮工厂类中定义的方法。这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的按钮类型,只需要为这种新类型的按钮创建一个具体的工厂类就可以获得该新按钮的实例,这一特点无疑使得工厂方法模式具有超越简单工厂模式的优越性,更加符合“**开闭原则**”。 - -## 2.2. 模式定义 -**工厂方法模式**(Factory Method Pattern)又称为工厂模式,也叫 **虚拟构造器(Virtual Constructor)模式** 或者 **多态工厂(Polymorphic Factory)模式**,它属于类 **创建型模式**。在工厂方法模式中,工 **厂父类** 负责定义创建产品对象的公共接口,而 **工厂子类** 则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。 - -## 2.3. 模式结构 -工厂方法模式包含如下角色: - -Product:抽象产品 -ConcreteProduct:具体产品 -Factory:抽象工厂 -ConcreteFactory:具体工厂 - -## 2.6. 模式分析 -工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了 *面向对象的多态性*,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责哪一个产品类被实例化这种细节,这使得工厂方法模式可以允许系统在 *不修改工厂角色的情况下引进新产品*。 - -## 2.7. 实例 -日志记录器 -某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等,且用户可以根据要求动态选择日志记录方式, 现使用工厂方法模式设计该系统。 - -##2.8. 工厂方法模式的优点 -1. 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。 -2. 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。 -3. 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个 **具体工厂和具体产品** 就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。 -## 2.9. 工厂方法模式的缺点 -1. 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。 -2. 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。 -## 2.10. 适用环境 -在以下情况下可以使用工厂方法模式: -1. 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。 -2. 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。 -3. 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。 -## 2.11. 模式应用 -JDBC中的工厂方法: -``` Java - Connection conn=DriverManager.getConnection("jdbc:microsoft:sqlserver://loc - alhost:1433; DatabaseName=DB;user=sa;password="); - Statement statement=conn.createStatement(); - ResultSet rs=statement.executeQuery("select * from UserInfo"); -``` -## 2.12. 模式扩展 -1. 使用多个工厂方法:在抽象工厂角色中可以定义多个工厂方法,从而使具体工厂角色实现这些不同的工厂方法,这些方法可以包含不同的业务逻辑,以满足对不同的产品对象的需求。 -2. 产品对象的重复使用:工厂对象将已经创建过的产品保存到一个集合(如数组、List等)中,然后根据客户对产品的请求,对集合进行查询。如果有满足要求的产品对象,就直接将该产品返回客户端;如果集合中没有这样的产品对象,那么就创建一个新的满足要求的产品对象,然后将这个对象在增加到集合中,再返回给客户端。 -3. 多态性的丧失和模式的退化:如果工厂仅仅返回一个具体产品对象,便违背了工厂方法的用意,发生退化,此时就不再是工厂方法模式了。一般来说,工厂对象应当有一个抽象的父类型,如果工厂等级结构中只有一个具体工厂类的话,抽象工厂就可以省略,也将发生了退化。当只有一个具体工厂,在具体工厂中可以创建所有的产品对象,并且工厂方法设计为静态方法时,工厂方法模式就退化成简单工厂模式。 -## 2.13. 总结 -1. 工厂方法模式又称为工厂模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。 -2. 工厂方法模式包含四个角色:抽象产品是定义产品的接口,是工厂方法模式所创建对象的超类型,即产品对象的共同父类或接口;具体产品实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,它们之间往往一一对应;抽象工厂中声明了工厂方法,用于返回一个产品,它是工厂方法模式的核心,任何在模式中创建对象的工厂类都必须实现该接口;具体工厂是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户调用,返回一个具体产品类的实例。 -3. 工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。 -4. 工厂方法模式的主要优点是增加新的产品类时无须修改现有系统,并封装了产品对象的创建细节,系统具有良好的灵活性和可扩展性;其缺点在于增加新产品的同时需要增加新的工厂,导致系统类的个数成对增加,在一定程度上增加了系统的复杂性。 -5. 工厂方法模式适用情况包括:一个类不知道它所需要的对象的类;一个类通过其子类来指定创建哪个对象;将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。 +## 2.1. 模式动机 +现在对该系统进行修改,不再设计一个按钮工厂类来统一负责所有产品的创建,而是将具体按钮的创建过程交给专门的工厂子类去完成,我们先定义一个 **抽象的按钮工厂类**,再定义 **具体的工厂类** 来生成 **圆形按钮、矩形按钮、菱形按钮** 等,它们实现在抽象按钮工厂类中定义的方法。这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的按钮类型,只需要为这种新类型的按钮创建一个具体的工厂类就可以获得该新按钮的实例,这一特点无疑使得工厂方法模式具有超越简单工厂模式的优越性,更加符合“**开闭原则**”。 + +## 2.2. 模式定义 +**工厂方法模式**(Factory Method Pattern)又称为工厂模式,也叫 **虚拟构造器(Virtual Constructor)模式** 或者 **多态工厂(Polymorphic Factory)模式**,它属于类 **创建型模式**。在工厂方法模式中,工 **厂父类** 负责定义创建产品对象的公共接口,而 **工厂子类** 则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。 + +## 2.3. 模式结构 +工厂方法模式包含如下角色: + +Product:抽象产品 +ConcreteProduct:具体产品 +Factory:抽象工厂 +ConcreteFactory:具体工厂 + +## 2.6. 模式分析 +工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了 *面向对象的多态性*,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责哪一个产品类被实例化这种细节,这使得工厂方法模式可以允许系统在 *不修改工厂角色的情况下引进新产品*。 + +## 2.7. 实例 +日志记录器 +某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等,且用户可以根据要求动态选择日志记录方式, 现使用工厂方法模式设计该系统。 + +##2.8. 工厂方法模式的优点 +1. 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。 +2. 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。 +3. 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个 **具体工厂和具体产品** 就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。 +## 2.9. 工厂方法模式的缺点 +1. 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。 +2. 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。 +## 2.10. 适用环境 +在以下情况下可以使用工厂方法模式: +1. 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。 +2. 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。 +3. 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。 +## 2.11. 模式应用 +JDBC中的工厂方法: +``` Java + Connection conn=DriverManager.getConnection("jdbc:microsoft:sqlserver://loc + alhost:1433; DatabaseName=DB;user=sa;password="); + Statement statement=conn.createStatement(); + ResultSet rs=statement.executeQuery("select * from UserInfo"); +``` +## 2.12. 模式扩展 +1. 使用多个工厂方法:在抽象工厂角色中可以定义多个工厂方法,从而使具体工厂角色实现这些不同的工厂方法,这些方法可以包含不同的业务逻辑,以满足对不同的产品对象的需求。 +2. 产品对象的重复使用:工厂对象将已经创建过的产品保存到一个集合(如数组、List等)中,然后根据客户对产品的请求,对集合进行查询。如果有满足要求的产品对象,就直接将该产品返回客户端;如果集合中没有这样的产品对象,那么就创建一个新的满足要求的产品对象,然后将这个对象在增加到集合中,再返回给客户端。 +3. 多态性的丧失和模式的退化:如果工厂仅仅返回一个具体产品对象,便违背了工厂方法的用意,发生退化,此时就不再是工厂方法模式了。一般来说,工厂对象应当有一个抽象的父类型,如果工厂等级结构中只有一个具体工厂类的话,抽象工厂就可以省略,也将发生了退化。当只有一个具体工厂,在具体工厂中可以创建所有的产品对象,并且工厂方法设计为静态方法时,工厂方法模式就退化成简单工厂模式。 +## 2.13. 总结 +1. 工厂方法模式又称为工厂模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。 +2. 工厂方法模式包含四个角色:抽象产品是定义产品的接口,是工厂方法模式所创建对象的超类型,即产品对象的共同父类或接口;具体产品实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,它们之间往往一一对应;抽象工厂中声明了工厂方法,用于返回一个产品,它是工厂方法模式的核心,任何在模式中创建对象的工厂类都必须实现该接口;具体工厂是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户调用,返回一个具体产品类的实例。 +3. 工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。 +4. 工厂方法模式的主要优点是增加新的产品类时无须修改现有系统,并封装了产品对象的创建细节,系统具有良好的灵活性和可扩展性;其缺点在于增加新产品的同时需要增加新的工厂,导致系统类的个数成对增加,在一定程度上增加了系统的复杂性。 +5. 工厂方法模式适用情况包括:一个类不知道它所需要的对象的类;一个类通过其子类来指定创建哪个对象;将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。 diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-03 - \346\212\275\350\261\241\345\267\245\345\216\202\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-03 - \346\212\275\350\261\241\345\267\245\345\216\202\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-03 - \346\212\275\350\261\241\345\267\245\345\216\202\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-03 - \346\212\275\350\261\241\345\267\245\345\216\202\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-04 - \345\273\272\351\200\240\350\200\205\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-04 - \345\273\272\351\200\240\350\200\205\346\250\241\345\274\217.md" similarity index 97% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-04 - \345\273\272\351\200\240\350\200\205\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-04 - \345\273\272\351\200\240\350\200\205\346\250\241\345\274\217.md" index dc9df8ab..2f854197 100644 --- "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-04 - \345\273\272\351\200\240\350\200\205\346\250\241\345\274\217.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-04 - \345\273\272\351\200\240\350\200\205\346\250\241\345\274\217.md" @@ -1,63 +1,63 @@ -# Builder模式 ---- - -##1. 模式介绍 ---- - -###1.1 模式的定义 - -将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 - -###1.2 模式的使用场景 - -1. 相同的方法,不同的执行顺序,产生不同的事件结果时; -2. 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时; -3. 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适; - - -###1.3 Android源码中的模式实现 - -在Android源码中,我们最常用到的Builder模式就是AlertDialog.Builder, 使用该Builder来构建复杂的AlertDialog对象。简单示例如下 : - -``` -//显示基本的AlertDialog - private void showDialog(Context context) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setIcon(R.drawable.icon); - builder.setTitle("Title"); - builder.setMessage("Message"); - builder.setPositiveButton("Button1", - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - setTitle("点击了对话框上的Button1"); - } - }); - builder.setNeutralButton("Button2", - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - setTitle("点击了对话框上的Button2"); - } - }); - builder.setNegativeButton("Button3", - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - setTitle("点击了对话框上的Button3"); - } - }); - builder.create().show(); // 构建AlertDialog, 并且显示 - } -``` - -##2. 优点与缺点 ---- - -###2.1 优点 - -* 良好的封装性, 使用建造者模式可以使客户端不必知道产品内部组成的细节; -* 建造者独立,容易扩展; -* 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。 - -###2.2 缺点 - -* 会产生多余的Builder对象以及Director对象,消耗内存; -* 对象的构建过程暴露。 +# Builder模式 +--- + +##1. 模式介绍 +--- + +###1.1 模式的定义 + +将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 + +###1.2 模式的使用场景 + +1. 相同的方法,不同的执行顺序,产生不同的事件结果时; +2. 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时; +3. 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适; + + +###1.3 Android源码中的模式实现 + +在Android源码中,我们最常用到的Builder模式就是AlertDialog.Builder, 使用该Builder来构建复杂的AlertDialog对象。简单示例如下 : + +``` +//显示基本的AlertDialog + private void showDialog(Context context) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setIcon(R.drawable.icon); + builder.setTitle("Title"); + builder.setMessage("Message"); + builder.setPositiveButton("Button1", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + setTitle("点击了对话框上的Button1"); + } + }); + builder.setNeutralButton("Button2", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + setTitle("点击了对话框上的Button2"); + } + }); + builder.setNegativeButton("Button3", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + setTitle("点击了对话框上的Button3"); + } + }); + builder.create().show(); // 构建AlertDialog, 并且显示 + } +``` + +##2. 优点与缺点 +--- + +###2.1 优点 + +* 良好的封装性, 使用建造者模式可以使客户端不必知道产品内部组成的细节; +* 建造者独立,容易扩展; +* 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。 + +###2.2 缺点 + +* 会产生多余的Builder对象以及Director对象,消耗内存; +* 对象的构建过程暴露。 diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-05 - \345\216\237\345\236\213\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-05 - \345\216\237\345\236\213\346\250\241\345\274\217.md" similarity index 97% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-05 - \345\216\237\345\236\213\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-05 - \345\216\237\345\236\213\346\250\241\345\274\217.md" index 1fcd86ea..b7ddb14b 100644 --- "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-05 - \345\216\237\345\236\213\346\250\241\345\274\217.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-05 - \345\216\237\345\236\213\346\250\241\345\274\217.md" @@ -1,41 +1,41 @@ -原型模式是软件开发中一种创造性的设计模式。 -当要创建的对象的类型由一个原型实例确定时,它被克隆以生成新的对象。此模式用于:**避免客户端应用程序中的对象生成器的子类**, -如抽象工厂模式。-避免以标准方式创建新对象的固有成本(例如,使用“新”关键字) - - -#原型模式 ---- - -##模式介绍 - -###模式的定义 - -用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 - -### 模式的使用场景 - -1. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等,通过原型拷贝避免这些消耗; -2. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式; -3. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。 - -##Android源码中的模式实现 - -Intent中使用了原型模式 - -``` -Uri uri = Uri.parse("smsto:0800000123"); - Intent shareIntent = new Intent(Intent.ACTION_SENDTO, uri); - shareIntent.putExtra("sms_body", "The SMS text"); - - Intent intent = (Intent)shareIntent.clone() ; - startActivity(intent); -``` - -##优点与缺点 - -###优点 -原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。 - - -###缺点 -这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,在实际开发当中应该注意这个潜在的问题。优点就是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。 +原型模式是软件开发中一种创造性的设计模式。 +当要创建的对象的类型由一个原型实例确定时,它被克隆以生成新的对象。此模式用于:**避免客户端应用程序中的对象生成器的子类**, +如抽象工厂模式。-避免以标准方式创建新对象的固有成本(例如,使用“新”关键字) + + +#原型模式 +--- + +##模式介绍 + +###模式的定义 + +用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 + +### 模式的使用场景 + +1. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等,通过原型拷贝避免这些消耗; +2. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式; +3. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。 + +##Android源码中的模式实现 + +Intent中使用了原型模式 + +``` +Uri uri = Uri.parse("smsto:0800000123"); + Intent shareIntent = new Intent(Intent.ACTION_SENDTO, uri); + shareIntent.putExtra("sms_body", "The SMS text"); + + Intent intent = (Intent)shareIntent.clone() ; + startActivity(intent); +``` + +##优点与缺点 + +###优点 +原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。 + + +###缺点 +这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,在实际开发当中应该注意这个潜在的问题。优点就是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。 diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-06 - \345\215\225\344\276\213\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-06 - \345\215\225\344\276\213\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/01-06 - \345\215\225\344\276\213\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/01-06 - \345\215\225\344\276\213\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02- \347\273\223\346\236\204\345\236\213\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02- \347\273\223\346\236\204\345\236\213\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02- \347\273\223\346\236\204\345\236\213\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02- \347\273\223\346\236\204\345\236\213\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-01- \351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-01- \351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" similarity index 97% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-01- \351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-01- \351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" index d7491f43..d9c3693d 100644 --- "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-01- \351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-01- \351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" @@ -1,13 +1,13 @@ - -适配器可以帮助两个不兼容的接口一起工作。这是真实世界的定义适配器。 - -接口可能是不兼容的,但内部功能应该符合需要。 - -适配器设计模式允许其他不兼容类通过转换一起工作。 - -一个类的接口成为客户端期望的接口。 - -适配器模式有两种变体: -类适配器实现适配器的接口,而对象适配器使用合成器在适配器对象中包含适配器。 - -本示例使用对象适配器方法。 + +适配器可以帮助两个不兼容的接口一起工作。这是真实世界的定义适配器。 + +接口可能是不兼容的,但内部功能应该符合需要。 + +适配器设计模式允许其他不兼容类通过转换一起工作。 + +一个类的接口成为客户端期望的接口。 + +适配器模式有两种变体: +类适配器实现适配器的接口,而对象适配器使用合成器在适配器对象中包含适配器。 + +本示例使用对象适配器方法。 diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-02- \346\241\245\346\216\245\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-02- \346\241\245\346\216\245\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-02- \346\241\245\346\216\245\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-02- \346\241\245\346\216\245\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-03- \347\273\204\345\220\210\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-03- \347\273\204\345\220\210\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-03- \347\273\204\345\220\210\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-03- \347\273\204\345\220\210\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-04- \350\243\205\351\245\260\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-04- \350\243\205\351\245\260\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-04- \350\243\205\351\245\260\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-04- \350\243\205\351\245\260\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-05- \345\244\226\350\247\202\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-05- \345\244\226\350\247\202\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-05- \345\244\226\350\247\202\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-05- \345\244\226\350\247\202\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-06- \344\272\253\345\205\203\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-06- \344\272\253\345\205\203\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-06- \344\272\253\345\205\203\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-06- \344\272\253\345\205\203\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-07- \344\273\243\347\220\206\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-07- \344\273\243\347\220\206\346\250\241\345\274\217.md" similarity index 99% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-07- \344\273\243\347\220\206\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-07- \344\273\243\347\220\206\346\250\241\345\274\217.md" index 2cf8125b..79e4cde6 100644 --- "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-07- \344\273\243\347\220\206\346\250\241\345\274\217.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-07- \344\273\243\347\220\206\346\250\241\345\274\217.md" @@ -1,57 +1,57 @@ -## 6.1. 模式动机 -在某些情况下,一个客户不想或者不能 **直接引用** 一个对象,此时可以通过一个称之为“代理”的第三者来实现 **间接引用**。代理对象可以在客户端和目标对象之间起到 **中介** 的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务。 - -通过引入一个 **新的对象**(如小图片和远程代理 对象)来 **实现** **对** **真实对象** 的 **操作** 或者 **将新的对象作为真实对象的一个替身**,这种实现机制即 为 **代理模式**,通过引入代理对象来间接访问一 个对象,这就是代理模式的模式动机。 - -## 6.2. 模式定义 -代理模式(Proxy Pattern) :给某一个对象提供一个代 理,并由代理对象控制对原对象的引用。代理模式的英 文叫做Proxy或Surrogate,它是一种 **对象结构型** 模式。 - -## 6.3. 模式结构 -代理模式包含如下角色: - -Subject: 抽象主题角色 -Proxy: 代理主题角色 -RealSubject: 真实主题角色 - -## 6.8. 优点 -代理模式的优点 -1. 代理模式能够协调调用者和被调用者,在一定程度上 **降低了系统的耦合度**。 -2. **远程代理** 使得客户端可以访问在 **远程机器上的对象**,远程机器 可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。 -3. 虚拟代理通过使用一个小对象来代表一个大对象,可以 **减少系统资源的消耗**,**对系统进行优化并提高运行速度**。 -4. 保护代理可以控制对 **真实对象的使用权限**。 - -## 6.9. 缺点 -代理模式的缺点 -1. 由于在客户端和真实主题之间增加了代理对象,因此 有些类型的代理模式可能会造成请求的 **处理速度变慢**。 -2. 实现代理模式需要额外的工作,有些代理模式的实现 **非常复杂**。 - -## 6.10. 适用环境 -根据代理模式的使用目的,常见的代理模式有以下几种类型: - -**远程(Remote)代理**:为一个位于不同的地址空间的对象提供一个本地 的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在 另一台主机中,远程代理又叫做大使(Ambassador)。 -**虚拟(Virtual)代理**:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。 -**Copy-on-Write代理**:它是虚拟代理的一种,把复制(克隆)操作延迟 到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个 开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。 -**保护(Protect or Access)代理**:控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。 -**缓冲(Cache)代理**:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。 -**防火墙(Firewall)代理**:保护目标不让恶意用户接近。 -**同步化(Synchronization)代理**:使几个用户能够同时使用一个对象而没有冲突。 -**智能引用(Smart Reference)代理**:当一个对象被引用时,提供一些额外的操作,如将此对象被调用的次数记录下来等。 - -## 6.11. 模式应用 -EJB、Web Service等分布式技术都是代理模式的应用。在EJB中使用了RMI机制,远程服务器中的企业级Bean在本地有一个桩代理,客户端通过桩来调用远程对象中定义的方法,而无须直接与远程对象交互。在EJB的使用中需要提供一个公共的接口,客户端针对该接口进行编程,无须知道桩以及远程EJB的实现细节。 - -## 6.12. 模式扩展 -几种常用的代理模式 -**图片代理**:一个很常见的代理模式的应用实例就是对大图浏览的控制。 -用户通过浏览器访问网页时先不加载真实的大图,而是通过代理对象的方法来进行处理,在代理对象的方法中,先使用一个线程向客户端浏览器加载一个小图片,然后在后台使用另一个线程来调用大图片的加载方法将大图片加载到客户端。当需要浏览大图片时,再将大图片在新网页中显示。如果用户在浏览大图时加载工作还没有完成,可以再启动一个线程来显示相应的提示信息。通过代理技术结合多线程编程将真实图片的加载放到后台来操作,不影响前台图片的浏览。 -**远程代理**:远程代理可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理的远程业务对象是局域的而不是远程的,而远程代理对象承担了大部分的网络通信工作。 -**虚拟代理**:当一个对象的加载十分耗费资源的时候,虚拟代理的优势就非常明显地体现出来了。虚拟代理模式是一种内存节省技术,那些占用大量内存或处理复杂的对象将推迟到使用它的时候才创建。 --在应用程序启动的时候,可以用代理对象代替真实对象初始化,节省了内存的占用,并大大加速了系统的启动时间。 - -**动态代理** -动态代理是一种较为高级的代理模式,它的典型应用就是 **Spring AOP**。 -在传统的代理模式中,客户端通过Proxy调用RealSubject类的request()方法,同时还在代理类中封装了其他方法(如preRequest()和postRequest()),可以处理一些其他问题。 -如果按照这种方法使用代理模式,那么真实主题角色必须是事先已经存在的,并将其作为代理对象的内部成员属性。如果一个真实主题角色必须对应一个代理主题角色,这将导致系统中的类个数急剧增加,因此需要想办法减少系统中类的个数,此外,如何在事先不知道真实主题角色的情况下使用代理主题角色,这都是动态代理需要解决的问题。 - -## 6.13. 总结 -在代理模式中,要求给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫做Proxy或Surrogate,它是一种对象结构型模式。 - 代理模式包含三个角色:抽象主题角色声明了真实主题和代理主题的共同接口;代理主题角色内部包含对真实主题的引用,从而可以在任何时候操作真实主题对象;真实主题角色定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的方法。 - 代理模式的优点在于能够协调调用者和被调用者,在一定程度上降低了系统的耦合度;其缺点在于由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,并且实现代理模式需要额外的工作,有些代理模式的实现非常复杂。远程代理为一个位于不同的地址空间的对象提供一个本地的代表对象,它使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。- 如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建,这个小对象称为虚拟代理。虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。 - 保护代理可以控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。 +## 6.1. 模式动机 +在某些情况下,一个客户不想或者不能 **直接引用** 一个对象,此时可以通过一个称之为“代理”的第三者来实现 **间接引用**。代理对象可以在客户端和目标对象之间起到 **中介** 的作用,并且可以通过代理对象去掉客户不能看到 的内容和服务或者添加客户需要的额外服务。 + +通过引入一个 **新的对象**(如小图片和远程代理 对象)来 **实现** **对** **真实对象** 的 **操作** 或者 **将新的对象作为真实对象的一个替身**,这种实现机制即 为 **代理模式**,通过引入代理对象来间接访问一 个对象,这就是代理模式的模式动机。 + +## 6.2. 模式定义 +代理模式(Proxy Pattern) :给某一个对象提供一个代 理,并由代理对象控制对原对象的引用。代理模式的英 文叫做Proxy或Surrogate,它是一种 **对象结构型** 模式。 + +## 6.3. 模式结构 +代理模式包含如下角色: + +Subject: 抽象主题角色 +Proxy: 代理主题角色 +RealSubject: 真实主题角色 + +## 6.8. 优点 +代理模式的优点 +1. 代理模式能够协调调用者和被调用者,在一定程度上 **降低了系统的耦合度**。 +2. **远程代理** 使得客户端可以访问在 **远程机器上的对象**,远程机器 可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。 +3. 虚拟代理通过使用一个小对象来代表一个大对象,可以 **减少系统资源的消耗**,**对系统进行优化并提高运行速度**。 +4. 保护代理可以控制对 **真实对象的使用权限**。 + +## 6.9. 缺点 +代理模式的缺点 +1. 由于在客户端和真实主题之间增加了代理对象,因此 有些类型的代理模式可能会造成请求的 **处理速度变慢**。 +2. 实现代理模式需要额外的工作,有些代理模式的实现 **非常复杂**。 + +## 6.10. 适用环境 +根据代理模式的使用目的,常见的代理模式有以下几种类型: + +**远程(Remote)代理**:为一个位于不同的地址空间的对象提供一个本地 的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在 另一台主机中,远程代理又叫做大使(Ambassador)。 +**虚拟(Virtual)代理**:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。 +**Copy-on-Write代理**:它是虚拟代理的一种,把复制(克隆)操作延迟 到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个 开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。 +**保护(Protect or Access)代理**:控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。 +**缓冲(Cache)代理**:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。 +**防火墙(Firewall)代理**:保护目标不让恶意用户接近。 +**同步化(Synchronization)代理**:使几个用户能够同时使用一个对象而没有冲突。 +**智能引用(Smart Reference)代理**:当一个对象被引用时,提供一些额外的操作,如将此对象被调用的次数记录下来等。 + +## 6.11. 模式应用 +EJB、Web Service等分布式技术都是代理模式的应用。在EJB中使用了RMI机制,远程服务器中的企业级Bean在本地有一个桩代理,客户端通过桩来调用远程对象中定义的方法,而无须直接与远程对象交互。在EJB的使用中需要提供一个公共的接口,客户端针对该接口进行编程,无须知道桩以及远程EJB的实现细节。 + +## 6.12. 模式扩展 +几种常用的代理模式 +**图片代理**:一个很常见的代理模式的应用实例就是对大图浏览的控制。 +用户通过浏览器访问网页时先不加载真实的大图,而是通过代理对象的方法来进行处理,在代理对象的方法中,先使用一个线程向客户端浏览器加载一个小图片,然后在后台使用另一个线程来调用大图片的加载方法将大图片加载到客户端。当需要浏览大图片时,再将大图片在新网页中显示。如果用户在浏览大图时加载工作还没有完成,可以再启动一个线程来显示相应的提示信息。通过代理技术结合多线程编程将真实图片的加载放到后台来操作,不影响前台图片的浏览。 +**远程代理**:远程代理可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理的远程业务对象是局域的而不是远程的,而远程代理对象承担了大部分的网络通信工作。 +**虚拟代理**:当一个对象的加载十分耗费资源的时候,虚拟代理的优势就非常明显地体现出来了。虚拟代理模式是一种内存节省技术,那些占用大量内存或处理复杂的对象将推迟到使用它的时候才创建。 +-在应用程序启动的时候,可以用代理对象代替真实对象初始化,节省了内存的占用,并大大加速了系统的启动时间。 + +**动态代理** +动态代理是一种较为高级的代理模式,它的典型应用就是 **Spring AOP**。 +在传统的代理模式中,客户端通过Proxy调用RealSubject类的request()方法,同时还在代理类中封装了其他方法(如preRequest()和postRequest()),可以处理一些其他问题。 +如果按照这种方法使用代理模式,那么真实主题角色必须是事先已经存在的,并将其作为代理对象的内部成员属性。如果一个真实主题角色必须对应一个代理主题角色,这将导致系统中的类个数急剧增加,因此需要想办法减少系统中类的个数,此外,如何在事先不知道真实主题角色的情况下使用代理主题角色,这都是动态代理需要解决的问题。 + +## 6.13. 总结 +在代理模式中,要求给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫做Proxy或Surrogate,它是一种对象结构型模式。 - 代理模式包含三个角色:抽象主题角色声明了真实主题和代理主题的共同接口;代理主题角色内部包含对真实主题的引用,从而可以在任何时候操作真实主题对象;真实主题角色定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的方法。 - 代理模式的优点在于能够协调调用者和被调用者,在一定程度上降低了系统的耦合度;其缺点在于由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,并且实现代理模式需要额外的工作,有些代理模式的实现非常复杂。远程代理为一个位于不同的地址空间的对象提供一个本地的代表对象,它使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。- 如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建,这个小对象称为虚拟代理。虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。 - 保护代理可以控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。 diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-08- \345\247\224\346\264\276\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-08- \345\247\224\346\264\276\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-08- \345\247\224\346\264\276\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-08- \345\247\224\346\264\276\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-09\344\273\243\347\220\206 vs \345\247\224\346\211\230 \350\257\255\344\271\211.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-09\344\273\243\347\220\206 vs \345\247\224\346\211\230 \350\257\255\344\271\211.md" similarity index 99% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-09\344\273\243\347\220\206 vs \345\247\224\346\211\230 \350\257\255\344\271\211.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-09\344\273\243\347\220\206 vs \345\247\224\346\211\230 \350\257\255\344\271\211.md" index 6bf65c4c..24900b14 100644 --- "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/02-09\344\273\243\347\220\206 vs \345\247\224\346\211\230 \350\257\255\344\271\211.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/02-09\344\273\243\347\220\206 vs \345\247\224\346\211\230 \350\257\255\344\271\211.md" @@ -1,4 +1,4 @@ - -proxy :译为代理, 被代理方(B)与代理方(A)的接口完全一致。 主要使用场景(语义)应该是:为简化编程(或无法操作B),不直接把请求交给被代理方(B),而把请求交给代码方(A),由代理方与被代理方进行通信,以完成请求。 - -delegete : 译为委托,主要语义是:一件事情(或一个请求)对象本身不知道怎样处理,对象把请求交给其它对象来做。 + +proxy :译为代理, 被代理方(B)与代理方(A)的接口完全一致。 主要使用场景(语义)应该是:为简化编程(或无法操作B),不直接把请求交给被代理方(B),而把请求交给代码方(A),由代理方与被代理方进行通信,以完成请求。 + +delegete : 译为委托,主要语义是:一件事情(或一个请求)对象本身不知道怎样处理,对象把请求交给其它对象来做。 diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03- \350\241\214\344\270\272\345\236\213\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03- \350\241\214\344\270\272\345\236\213\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03- \350\241\214\344\270\272\345\236\213\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03- \350\241\214\344\270\272\345\236\213\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-01- \345\221\275\344\273\244\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-01- \345\221\275\344\273\244\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-01- \345\221\275\344\273\244\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-01- \345\221\275\344\273\244\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-02- \344\270\255\344\273\213\350\200\205\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-02- \344\270\255\344\273\213\350\200\205\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-02- \344\270\255\344\273\213\350\200\205\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-02- \344\270\255\344\273\213\350\200\205\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-03- \350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-03- \350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" similarity index 99% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-03- \350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-03- \350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" index 974a6669..6593473d 100644 --- "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-03- \350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-03- \350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" @@ -1,2 +1,2 @@ -## 3.1. 模式动机 -建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。 +## 3.1. 模式动机 +建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。 diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-04- \347\212\266\346\200\201\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-04- \347\212\266\346\200\201\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-04- \347\212\266\346\200\201\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-04- \347\212\266\346\200\201\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-05- \347\255\226\347\225\245\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-05- \347\255\226\347\225\245\346\250\241\345\274\217.md" similarity index 99% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-05- \347\255\226\347\225\245\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-05- \347\255\226\347\225\245\346\250\241\345\274\217.md" index 4f4eb850..a360e19d 100644 --- "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-05- \347\255\226\347\225\245\346\250\241\345\274\217.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-05- \347\255\226\347\225\245\346\250\241\345\274\217.md" @@ -1,60 +1,60 @@ -策略模式(也称为策略模式)是一种软件设计模式,可以在 **运行时选择算法的行为**。 - -## 5.1. 模式动机 -完成一项任务,往往可以有多种不同的方式,每一种方式称为一个策略,我们可以根据环境或者条件的不同选择不同的策略来完成该项任务。 -在软件开发中也常常遇到类似的情况,实现某一个功能有多个途径,此时可以 **使用一种设计模式来使得系统可以灵活地选择解决途径,也能够方便地增加新的解决途径**。 -在软件系统中,有许多算法可以实现某一功能,如查找、排序等,一种常用的方法是 **硬编码(Hard Coding)** 在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;当然也可以将这些查找算法封装在一个统一的方法中,通过if…else…等条件判断语句来进行选择。这两种实现方法我们都可以称之为硬编码,如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。 -除了提供专门的查找算法类之外,还可以在客户端程序中直接包含算法代码,这种做法更不可取,将导致客户端程序庞大而且难以维护,如果存在大量可供选择的算法时问题将变得更加严重。 -为了解决这些问题,可以 **定义一些独立的类来封装不同的算法**,每一个类封装一个具体的算法,在这里,**每一个封装算法的类我们都可以称之为策略(Strategy)**,为了保证这些策略的一致性,一般会用 **一个抽象的策略类** 来做算法的定义,而 **具体每种算法** 则对应于 **一个具体策略类** 。 - -## 5.2. 模式定义 -策略模式(Strategy Pattern):定义 **一系列算法**,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。 - -策略模式是一种对象行为型模式。 - -## 5.3. 模式结构 -策略模式包含如下角色: - -Context: 环境类 -Strategy: 抽象策略类 -ConcreteStrategy: 具体策略类 - -## 5.6. 模式分析 -1. 策略模式是一个比较容易理解和使用的设计模式,策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。 -2. 在策略模式中,应当由客户端自己决定在什么情况下使用什么具体策略角色。 -3. 策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中“退休”的方便,策略模式并不决定在何时使用何种算法,算法的选择由客户端来决定。这在一定程度上提高了系统的灵活性,但是客户端需要理解所有具体策略类之间的区别,以便选择合适的算法,这也是策略模式的缺点之一,在一定程度上增加了客户端的使用难度。 - -## 5.8. 优点 -策略模式的优点 - -1. 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。 -2. 策略模式提供了管理相关的算法族的办法。 -3. 策略模式提供了可以替换继承关系的办法。 -4. 使用策略模式可以避免使用多重条件转移语句。 - -## 5.9. 缺点 -策略模式的缺点 -1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。 -2. 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。 -## 5.10. 适用环境 -在以下情况下可以使用策略模式: - -1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 -2. 一个系统需要动态地在几种算法中选择一种。 -3. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。 -4. 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。 - -## 5.12. 模式扩展 -策略模式与状态模式 - -1. 可以通过环境类状态的个数来决定是使用策略模式还是状态模式。 -2. 策略模式的环境类自己选择一个具体策略类,具体策略类无须关心环境类;而状态模式的环境类由于外在因素需要放进一个具体状态中,以便通过其方法实现状态的切换,因此环境类和状态类之间存在一种双向的关联关系。 -3. 使用策略模式时,客户端需要知道所选的具体策略是哪一个,而使用状态模式时,客户端无须关心具体状态,环境类的状态会根据用户的操作自动转换。 -4. 如果系统中某个类的对象存在多种状态,不同状态下行为有差异,而且这些状态之间可以发生转换时使用状态模式;如果系统中某个类的某一行为存在多种实现方式,而且这些实现方式可以互换时使用策略模式。 - -## 5.13. 总结 -1. 在策略模式中定义了一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式。策略模式是一种对象行为型模式。 -2. 策略模式包含三个角色:环境类在解决某个问题时可以采用多种策略,在环境类中维护一个对抽象策略类的引用实例;抽象策略类为所支持的算法声明了抽象方法,是所有策略类的父类;具体策略类实现了在抽象策略类中定义的算法。 -3. 策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。 -4. 策略模式主要优点在于对“开闭原则”的完美支持,在不修改原有系统的基础上可以更换算法或者增加新的算法,它很好地管理算法族,提高了代码的复用性,是一种替换继承,避免多重条件转移语句的实现方式;其缺点在于客户端必须知道所有的策略类,并理解其区别,同时在一定程度上增加了系统中类的个数,可能会存在很多策略类。 -5. 策略模式适用情况包括:在一个系统里面有许多类,它们之间的区别仅在于它们的行为,使用策略模式可以动态地让一个对象在许多行为中选择一种行为;一个系统需要动态地在几种算法中选择一种;避免使用难以维护的多重条件选择语句;希望在具体策略类中封装算法和与相关的数据结构。 +策略模式(也称为策略模式)是一种软件设计模式,可以在 **运行时选择算法的行为**。 + +## 5.1. 模式动机 +完成一项任务,往往可以有多种不同的方式,每一种方式称为一个策略,我们可以根据环境或者条件的不同选择不同的策略来完成该项任务。 +在软件开发中也常常遇到类似的情况,实现某一个功能有多个途径,此时可以 **使用一种设计模式来使得系统可以灵活地选择解决途径,也能够方便地增加新的解决途径**。 +在软件系统中,有许多算法可以实现某一功能,如查找、排序等,一种常用的方法是 **硬编码(Hard Coding)** 在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;当然也可以将这些查找算法封装在一个统一的方法中,通过if…else…等条件判断语句来进行选择。这两种实现方法我们都可以称之为硬编码,如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。 +除了提供专门的查找算法类之外,还可以在客户端程序中直接包含算法代码,这种做法更不可取,将导致客户端程序庞大而且难以维护,如果存在大量可供选择的算法时问题将变得更加严重。 +为了解决这些问题,可以 **定义一些独立的类来封装不同的算法**,每一个类封装一个具体的算法,在这里,**每一个封装算法的类我们都可以称之为策略(Strategy)**,为了保证这些策略的一致性,一般会用 **一个抽象的策略类** 来做算法的定义,而 **具体每种算法** 则对应于 **一个具体策略类** 。 + +## 5.2. 模式定义 +策略模式(Strategy Pattern):定义 **一系列算法**,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。 + +策略模式是一种对象行为型模式。 + +## 5.3. 模式结构 +策略模式包含如下角色: + +Context: 环境类 +Strategy: 抽象策略类 +ConcreteStrategy: 具体策略类 + +## 5.6. 模式分析 +1. 策略模式是一个比较容易理解和使用的设计模式,策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。 +2. 在策略模式中,应当由客户端自己决定在什么情况下使用什么具体策略角色。 +3. 策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中“退休”的方便,策略模式并不决定在何时使用何种算法,算法的选择由客户端来决定。这在一定程度上提高了系统的灵活性,但是客户端需要理解所有具体策略类之间的区别,以便选择合适的算法,这也是策略模式的缺点之一,在一定程度上增加了客户端的使用难度。 + +## 5.8. 优点 +策略模式的优点 + +1. 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。 +2. 策略模式提供了管理相关的算法族的办法。 +3. 策略模式提供了可以替换继承关系的办法。 +4. 使用策略模式可以避免使用多重条件转移语句。 + +## 5.9. 缺点 +策略模式的缺点 +1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。 +2. 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。 +## 5.10. 适用环境 +在以下情况下可以使用策略模式: + +1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 +2. 一个系统需要动态地在几种算法中选择一种。 +3. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。 +4. 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。 + +## 5.12. 模式扩展 +策略模式与状态模式 + +1. 可以通过环境类状态的个数来决定是使用策略模式还是状态模式。 +2. 策略模式的环境类自己选择一个具体策略类,具体策略类无须关心环境类;而状态模式的环境类由于外在因素需要放进一个具体状态中,以便通过其方法实现状态的切换,因此环境类和状态类之间存在一种双向的关联关系。 +3. 使用策略模式时,客户端需要知道所选的具体策略是哪一个,而使用状态模式时,客户端无须关心具体状态,环境类的状态会根据用户的操作自动转换。 +4. 如果系统中某个类的对象存在多种状态,不同状态下行为有差异,而且这些状态之间可以发生转换时使用状态模式;如果系统中某个类的某一行为存在多种实现方式,而且这些实现方式可以互换时使用策略模式。 + +## 5.13. 总结 +1. 在策略模式中定义了一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式。策略模式是一种对象行为型模式。 +2. 策略模式包含三个角色:环境类在解决某个问题时可以采用多种策略,在环境类中维护一个对抽象策略类的引用实例;抽象策略类为所支持的算法声明了抽象方法,是所有策略类的父类;具体策略类实现了在抽象策略类中定义的算法。 +3. 策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。 +4. 策略模式主要优点在于对“开闭原则”的完美支持,在不修改原有系统的基础上可以更换算法或者增加新的算法,它很好地管理算法族,提高了代码的复用性,是一种替换继承,避免多重条件转移语句的实现方式;其缺点在于客户端必须知道所有的策略类,并理解其区别,同时在一定程度上增加了系统中类的个数,可能会存在很多策略类。 +5. 策略模式适用情况包括:在一个系统里面有许多类,它们之间的区别仅在于它们的行为,使用策略模式可以动态地让一个对象在许多行为中选择一种行为;一个系统需要动态地在几种算法中选择一种;避免使用难以维护的多重条件选择语句;希望在具体策略类中封装算法和与相关的数据结构。 diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-10- \346\250\241\346\235\277\346\226\271\346\263\225\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-10- \346\250\241\346\235\277\346\226\271\346\263\225\346\250\241\345\274\217.md" similarity index 98% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-10- \346\250\241\346\235\277\346\226\271\346\263\225\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-10- \346\250\241\346\235\277\346\226\271\346\263\225\346\250\241\345\274\217.md" index b8d348ac..f19cad57 100644 --- "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/03-10- \346\250\241\346\235\277\346\226\271\346\263\225\346\250\241\345\274\217.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/03-10- \346\250\241\346\235\277\346\226\271\346\263\225\346\250\241\345\274\217.md" @@ -1 +1 @@ -模板方法为算法定义了一个框架。 算法子类为空白部分提供实现。 +模板方法为算法定义了一个框架。 算法子类为空白部分提供实现。 diff --git "a/000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/README.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/README.md" similarity index 100% rename from "000 - 3 Design Patterns/\346\210\221\347\232\204\347\220\206\350\247\243/README.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\346\210\221\347\232\204\347\220\206\350\247\243/README.md" diff --git "a/000 - 3 Design Patterns/\347\255\226\347\225\245\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\347\255\226\347\225\245\346\250\241\345\274\217.md" similarity index 96% rename from "000 - 3 Design Patterns/\347\255\226\347\225\245\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\347\255\226\347\225\245\346\250\241\345\274\217.md" index da5b74e3..92dbce22 100644 --- "a/000 - 3 Design Patterns/\347\255\226\347\225\245\346\250\241\345\274\217.md" +++ "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\347\255\226\347\225\245\346\250\241\345\274\217.md" @@ -1,33 +1,33 @@ -#策略模式 ---- - -##模式的定义 - -策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。 - -注:针对同一类型操作,将复杂多样的处理方式分别开来,有选择的实现各自特有的操作。 - -##模式的使用场景 - -* 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时。 -* 需要安全的封装多种同一类型的操作时。 -* 出现同一抽象多个子类,而又需要使用if-else 或者 switch-case来选择时。 - -##Android源码中的模式实现 - - - - -策略模式主要用来分离算法,根据相同的行为抽象来做不同的具体策略实现。 - -##优缺点 - -###优点: - -* 结构清晰明了、使用简单直观。 -* 耦合度相对而言较低,扩展方便。 -* 操作封装也更为彻底,数据更为安全。 - -###缺点: - -* 随着策略的增加,子类也会变得繁多。 +#策略模式 +--- + +##模式的定义 + +策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。 + +注:针对同一类型操作,将复杂多样的处理方式分别开来,有选择的实现各自特有的操作。 + +##模式的使用场景 + +* 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时。 +* 需要安全的封装多种同一类型的操作时。 +* 出现同一抽象多个子类,而又需要使用if-else 或者 switch-case来选择时。 + +##Android源码中的模式实现 + + + + +策略模式主要用来分离算法,根据相同的行为抽象来做不同的具体策略实现。 + +##优缺点 + +###优点: + +* 结构清晰明了、使用简单直观。 +* 耦合度相对而言较低,扩展方便。 +* 操作封装也更为彻底,数据更为安全。 + +###缺点: + +* 随着策略的增加,子类也会变得繁多。 diff --git "a/000 - 3 Design Patterns/\347\256\200\345\215\225\345\267\245\345\216\202.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\347\256\200\345\215\225\345\267\245\345\216\202.md" similarity index 100% rename from "000 - 3 Design Patterns/\347\256\200\345\215\225\345\267\245\345\216\202.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\347\256\200\345\215\225\345\267\245\345\216\202.md" diff --git "a/000 - 3 Design Patterns/\350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\350\264\243\344\273\273\351\223\276\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\350\264\243\344\273\273\351\223\276\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\350\264\243\344\273\273\351\223\276\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\350\264\243\344\273\273\351\223\276\346\250\241\345\274\217.md" diff --git "a/000 - 3 Design Patterns/\351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" "b/000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" similarity index 100% rename from "000 - 3 Design Patterns/\351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" rename to "000 - 3 Design Patterns \350\256\276\350\256\241\346\250\241\345\274\217/\351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" diff --git "a/01 - JavaSE/0000 Java \345\216\206\345\217\262 .md" "b/01 - JavaSE Java\346\240\270\345\277\203/0000 Java \345\216\206\345\217\262 .md" similarity index 100% rename from "01 - JavaSE/0000 Java \345\216\206\345\217\262 .md" rename to "01 - JavaSE Java\346\240\270\345\277\203/0000 Java \345\216\206\345\217\262 .md" diff --git "a/01 - JavaSE/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/1.1.1 \345\244\232\347\272\277\347\250\213\344\271\213\345\206\205\345\255\230\345\217\257\350\247\201\346\200\247.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/1.1.1 \345\244\232\347\272\277\347\250\213\344\271\213\345\206\205\345\255\230\345\217\257\350\247\201\346\200\247.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/1.1.1 \345\244\232\347\272\277\347\250\213\344\271\213\345\206\205\345\255\230\345\217\257\350\247\201\346\200\247.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/1.1.1 \345\244\232\347\272\277\347\250\213\344\271\213\345\206\205\345\255\230\345\217\257\350\247\201\346\200\247.md" diff --git "a/01 - JavaSE/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/1.1.2 \345\206\205\345\255\230\346\250\241\345\236\213FAQ.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/1.1.2 \345\206\205\345\255\230\346\250\241\345\236\213FAQ.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/1.1.2 \345\206\205\345\255\230\346\250\241\345\236\213FAQ.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/1.1.2 \345\206\205\345\255\230\346\250\241\345\236\213FAQ.md" diff --git "a/01 - JavaSE/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/README.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/README.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/README.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.1 \345\206\205\345\255\230\346\250\241\345\236\213/README.md" diff --git "a/01 - JavaSE/01 - JVM/1.2 \345\206\205\345\255\230\347\256\241\347\220\206/README.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.2 \345\206\205\345\255\230\347\256\241\347\220\206/README.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/1.2 \345\206\205\345\255\230\347\256\241\347\220\206/README.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.2 \345\206\205\345\255\230\347\256\241\347\220\206/README.md" diff --git "a/01 - JavaSE/01 - JVM/1.3 \345\240\206\345\222\214\346\240\210/README.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.3 \345\240\206\345\222\214\346\240\210/README.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/1.3 \345\240\206\345\222\214\346\240\210/README.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.3 \345\240\206\345\222\214\346\240\210/README.md" diff --git "a/01 - JavaSE/01 - JVM/1.4 \345\236\203\345\234\276\345\233\236\346\224\266/README.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.4 \345\236\203\345\234\276\345\233\236\346\224\266/README.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/1.4 \345\236\203\345\234\276\345\233\236\346\224\266/README.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.4 \345\236\203\345\234\276\345\233\236\346\224\266/README.md" diff --git "a/01 - JavaSE/01 - JVM/1.5 \345\217\202\346\225\260\345\217\212\350\260\203\344\274\230/README.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.5 \345\217\202\346\225\260\345\217\212\350\260\203\344\274\230/README.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/1.5 \345\217\202\346\225\260\345\217\212\350\260\203\344\274\230/README.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/1.5 \345\217\202\346\225\260\345\217\212\350\260\203\344\274\230/README.md" diff --git a/01 - JavaSE/01 - JVM/JVM - all.md "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - all.md" similarity index 100% rename from 01 - JavaSE/01 - JVM/JVM - all.md rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - all.md" diff --git a/01 - JavaSE/01 - JVM/JVM - all2.md "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - all2.md" similarity index 100% rename from 01 - JavaSE/01 - JVM/JVM - all2.md rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - all2.md" diff --git a/01 - JavaSE/01 - JVM/JVM - tree.txt "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - tree.txt" similarity index 100% rename from 01 - JavaSE/01 - JVM/JVM - tree.txt rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - tree.txt" diff --git "a/01 - JavaSE/01 - JVM/JVM - \345\206\205\345\255\230\346\250\241\345\236\213.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \345\206\205\345\255\230\346\250\241\345\236\213.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/JVM - \345\206\205\345\255\230\346\250\241\345\236\213.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \345\206\205\345\255\230\346\250\241\345\236\213.md" diff --git "a/01 - JavaSE/01 - JVM/JVM - \345\210\206\345\214\272.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \345\210\206\345\214\272.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/JVM - \345\210\206\345\214\272.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \345\210\206\345\214\272.md" diff --git "a/01 - JavaSE/01 - JVM/JVM - \345\236\203\345\234\276\346\224\266\351\233\206.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \345\236\203\345\234\276\346\224\266\351\233\206.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/JVM - \345\236\203\345\234\276\346\224\266\351\233\206.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \345\236\203\345\234\276\346\224\266\351\233\206.md" diff --git "a/01 - JavaSE/01 - JVM/JVM - \347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/JVM - \347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \347\261\273\345\212\240\350\275\275\346\234\272\345\210\266.md" diff --git "a/01 - JavaSE/01 - JVM/JVM - \347\261\273\345\212\240\350\275\275\350\277\207\347\250\213.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \347\261\273\345\212\240\350\275\275\350\277\207\347\250\213.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/JVM - \347\261\273\345\212\240\350\275\275\350\277\207\347\250\213.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \347\261\273\345\212\240\350\275\275\350\277\207\347\250\213.md" diff --git "a/01 - JavaSE/01 - JVM/JVM - \350\260\203\344\274\230\346\200\273\347\273\223.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \350\260\203\344\274\230\346\200\273\347\273\223.md" similarity index 100% rename from "01 - JavaSE/01 - JVM/JVM - \350\260\203\344\274\230\346\200\273\347\273\223.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM - \350\260\203\344\274\230\346\200\273\347\273\223.md" diff --git "a/01 - JavaSE/01 - JVM/JVM \350\277\220\350\241\214\346\227\266\346\225\260\346\215\256\345\214\272.png" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM \350\277\220\350\241\214\346\227\266\346\225\260\346\215\256\345\214\272.png" similarity index 100% rename from "01 - JavaSE/01 - JVM/JVM \350\277\220\350\241\214\346\227\266\346\225\260\346\215\256\345\214\272.png" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM \350\277\220\350\241\214\346\227\266\346\225\260\346\215\256\345\214\272.png" diff --git "a/01 - JavaSE/01 - JVM/JVM\345\206\205\345\255\230\346\250\241\345\236\213.jpg" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\206\205\345\255\230\346\250\241\345\236\213.jpg" similarity index 100% rename from "01 - JavaSE/01 - JVM/JVM\345\206\205\345\255\230\346\250\241\345\236\213.jpg" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\206\205\345\255\230\346\250\241\345\236\213.jpg" diff --git "a/01 - JavaSE/01 - JVM/JVM\345\206\205\345\255\230\347\273\223\346\236\204.png" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\206\205\345\255\230\347\273\223\346\236\204.png" similarity index 100% rename from "01 - JavaSE/01 - JVM/JVM\345\206\205\345\255\230\347\273\223\346\236\204.png" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\206\205\345\255\230\347\273\223\346\236\204.png" diff --git "a/01 - JavaSE/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/01 - jps.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/01 - jps.md" similarity index 98% rename from "01 - JavaSE/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/01 - jps.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/01 - jps.md" index 2f413b24..1e29bdfb 100644 --- "a/01 - JavaSE/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/01 - jps.md" +++ "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/01 - jps.md" @@ -1,94 +1,94 @@ -jps位于jdk的bin目录下,其作用是显示当前系统的java进程情况,及其id号。 -jps相当于Solaris进程工具ps。 -不象”pgrep java”或”ps -ef grep java”,jps并不使用应用程序名来查找JVM实例。 -因此,它查找所有的Java应用程序,包括即使没有使用java执行体的那种(例如,定制的启动 器)。另外,jps仅查找当前用户的Java进程,而不是当前系统中的所有进程。 - -### 位置 -我们知道,很多Java命令都在jdk的JAVA_HOME/bin/目录下面,jps也不例外,他就在bin目录下,所以,他是java自带的一个命令。 -### 功能 -jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。 -### 原理 - -jdk中的jps命令可以显示当前运行的java进程以及相关参数,它的实现机制如下: -java程序在启动以后,会在java.io.tmpdir指定的目录下,就是临时文件夹里,生成一个类似于hsperfdata_User的文件夹,这个文件夹里在Linux中为 **/tmp/hsperfdata_{userName}/**,有几个文件,名字就是java进程的pid,因此列出当前运行的java进程,只是把这个目录里的文件名列一下而已。 至于系统的参数什么,就可以解析这几个文件获得。 -``` -hollis@hos:/tmp/hsperfdata_hollis -$ pwd -/tmp/hsperfdata_hollis -hollis@hos:/tmp/hsperfdata_hollis$ ll -total 48 -drwxr-xr-x 2 hollis hollis 4096 4月 16 10:54 ./ -drwxrwxrwt 7 root root 12288 4月 16 10:56 ../ --rw------- 1 hollis hollis 32768 4月 16 10:57 2679 -hollis@hos:/tmp/hsperfdata_hollis$ -``` -上面的内容就是我机器中/tmp/hsperfdata_hollis目录下的内容,其中2679就是我机器上当前运行中的java的进程的pid,我们执行jps验证一下: -``` -hollis@hos:/tmp/hsperfdata_hollis$ jps -2679 org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar -4445 Jps -``` -执行了jps命令之后,我们发现有两个java进程,一个是pid为2679的eclipse运行的进程,另外一个是pid为4445的jps使用的进程(他也是java命令,也要开一个进程) -使用 -想要学习一个命令,先来看看帮助,使用jps -help查看帮助: -``` -hollis@hos:/tmp/hsperfdata_hollis$ jps -help -usage: jps [-help] - jps [-q] [-mlvV] [] - -Definitions: - : [:] -``` -接下来,为了详细介绍这些参数,我们编写几个类,在main方法里写一个while(true)的循环,查看java进程情况。代码如下: -```java -package com.JavaCommand; -/** - * @author hollis - */ -public class JpsDemo { - public static void main(String[] args) { - while(true){ - System.out.println(1); - } - } -} -``` -`-q` 只显示pid,不显示class名称,jar文件名和传递给main 方法的参数 -hollis@hos:/tmp/hsperfdata_hollis$ **jps -q** -2679 -11421 -`-m` 输出传递给main 方法的参数,在嵌入式jvm上可能是null, 在这里,在启动main方法的时候,我给String[] args传递两个参数。hollis,chuang,执行 **jsp -m**: -``` -hollis@hos:/tmp/hsperfdata_hollis$ jps -m -12062 JpsDemo hollis,chuang -``` -`-l` 输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名 -``` -hollis@hos:/tmp/hsperfdata_hollis$ jps -l -12356 sun.tools.jps.Jps -2679 /home/hollis/tools/eclipse//plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar -12329 com.JavaCommand.JpsDemo -``` -`-v` 输出传递给JVM的参数 在这里,在启动main方法的时候,我给jvm传递一个参数:-Dfile.encoding=UTF-8,执行jps -v: -``` -hollis@hos:/tmp/hsperfdata_hollis$ jps -v -2679 org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar -Djava.library.path=/usr/lib/jni:/usr/lib/x86_64-linux-gnu/jni -Dosgi.requiredJavaVersion=1.6 -XX:MaxPermSize=256m -Xms40m -Xmx512m -13157 Jps -Denv.class.path=/home/hollis/tools/java/jdk1.7.0_71/lib:/home/hollis/tools/java/jdk1.7.0_71/jre/lib: -Dapplication.home=/home/hollis/tools/java/jdk1.7.0_71 -Xms8m -13083 JpsDemo -Dfile.encoding=UTF-8 -``` -PS:jps命令有个地方很不好,似乎只能显示当前用户的java进程,要显示其他用户的还是只能用unix/linux的`ps`命令。 -jps是我最常用的java命令。使用jps可以查看当前有哪些Java进程处于运行状态。如果我运行了一个web应用(使用tomcat、jboss、jetty等启动)的时候,我就可以使用jps查看启动情况。有的时候我想知道这个应用的日志会输出到哪里,或者启动的时候使用了哪些javaagent,那么我可以使用jps -v 查看进程的jvm参数情况。 - -### JPS失效处理 -现象: 用`ps -ef|grep java`能看到启动的java进程,但是用jps查看却不存在该进程的id。 -待会儿解释过之后就能知道在该情况下,jconsole、jvisualvm可能无法监控该进程,其他java自带工具也可能无法使用 -分析: jps、jconsole、jvisualvm等工具的数据来源就是这个文件(/tmp/hsperfdata_userName/pid)。所以当该文件不存在或是无法读取时就会出现jps无法查看该进程号,jconsole无法监控等问题 -原因: -(1)、磁盘读写、目录权限问题 若该用户没有权限写/tmp目录或是磁盘已满,则无法创建/tmp/hsperfdata_userName/pid文件。或该文件已经生成,但用户没有读权限 -(2)、临时文件丢失,被删除或是定期清理 对于linux机器,一般都会存在定时任务对临时文件夹进行清理,导致/tmp目录被清空。这也是我第一次碰到该现象的原因。常用的可能定时删除临时目录的工具为crontab、redhat的tmpwatch、ubuntu的tmpreaper等等 -这个导致的现象可能会是这样,用jconsole监控进程,发现在某一时段后进程仍然存在,但是却没有监控信息了。 -(3)、java进程信息文件存储地址被设置,不在/tmp目录下 上面我们在介绍时说默认会在/tmp/hsperfdata_userName目录保存进程信息,但由于以上1、2所述原因,可能导致该文件无法生成或是丢失,所以java启动时提供了参数(`-Djava.io.tmpdir`),可以对这个文件的位置进行设置,而jps、jconsole都只会从/tmp目录读取,而无法从设置后的目录读物信息,这是我第二次碰到该现象的原因 - -附: -1.如何给main传递参数 在eclipse中,鼠标右键->Run As->Run COnfiguations->Arguments->在Program arguments中写下要传的参数值 -1.如何给JVM传递参数 在eclipse中,鼠标右键->Run As->Run COnfiguations->Arguments->在VM arguments中写下要传的参数值(一般以-D开头) +jps位于jdk的bin目录下,其作用是显示当前系统的java进程情况,及其id号。 +jps相当于Solaris进程工具ps。 +不象”pgrep java”或”ps -ef grep java”,jps并不使用应用程序名来查找JVM实例。 +因此,它查找所有的Java应用程序,包括即使没有使用java执行体的那种(例如,定制的启动 器)。另外,jps仅查找当前用户的Java进程,而不是当前系统中的所有进程。 + +### 位置 +我们知道,很多Java命令都在jdk的JAVA_HOME/bin/目录下面,jps也不例外,他就在bin目录下,所以,他是java自带的一个命令。 +### 功能 +jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。 +### 原理 + +jdk中的jps命令可以显示当前运行的java进程以及相关参数,它的实现机制如下: +java程序在启动以后,会在java.io.tmpdir指定的目录下,就是临时文件夹里,生成一个类似于hsperfdata_User的文件夹,这个文件夹里在Linux中为 **/tmp/hsperfdata_{userName}/**,有几个文件,名字就是java进程的pid,因此列出当前运行的java进程,只是把这个目录里的文件名列一下而已。 至于系统的参数什么,就可以解析这几个文件获得。 +``` +hollis@hos:/tmp/hsperfdata_hollis +$ pwd +/tmp/hsperfdata_hollis +hollis@hos:/tmp/hsperfdata_hollis$ ll +total 48 +drwxr-xr-x 2 hollis hollis 4096 4月 16 10:54 ./ +drwxrwxrwt 7 root root 12288 4月 16 10:56 ../ +-rw------- 1 hollis hollis 32768 4月 16 10:57 2679 +hollis@hos:/tmp/hsperfdata_hollis$ +``` +上面的内容就是我机器中/tmp/hsperfdata_hollis目录下的内容,其中2679就是我机器上当前运行中的java的进程的pid,我们执行jps验证一下: +``` +hollis@hos:/tmp/hsperfdata_hollis$ jps +2679 org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar +4445 Jps +``` +执行了jps命令之后,我们发现有两个java进程,一个是pid为2679的eclipse运行的进程,另外一个是pid为4445的jps使用的进程(他也是java命令,也要开一个进程) +使用 +想要学习一个命令,先来看看帮助,使用jps -help查看帮助: +``` +hollis@hos:/tmp/hsperfdata_hollis$ jps -help +usage: jps [-help] + jps [-q] [-mlvV] [] + +Definitions: + : [:] +``` +接下来,为了详细介绍这些参数,我们编写几个类,在main方法里写一个while(true)的循环,查看java进程情况。代码如下: +```java +package com.JavaCommand; +/** + * @author hollis + */ +public class JpsDemo { + public static void main(String[] args) { + while(true){ + System.out.println(1); + } + } +} +``` +`-q` 只显示pid,不显示class名称,jar文件名和传递给main 方法的参数 +hollis@hos:/tmp/hsperfdata_hollis$ **jps -q** +2679 +11421 +`-m` 输出传递给main 方法的参数,在嵌入式jvm上可能是null, 在这里,在启动main方法的时候,我给String[] args传递两个参数。hollis,chuang,执行 **jsp -m**: +``` +hollis@hos:/tmp/hsperfdata_hollis$ jps -m +12062 JpsDemo hollis,chuang +``` +`-l` 输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名 +``` +hollis@hos:/tmp/hsperfdata_hollis$ jps -l +12356 sun.tools.jps.Jps +2679 /home/hollis/tools/eclipse//plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar +12329 com.JavaCommand.JpsDemo +``` +`-v` 输出传递给JVM的参数 在这里,在启动main方法的时候,我给jvm传递一个参数:-Dfile.encoding=UTF-8,执行jps -v: +``` +hollis@hos:/tmp/hsperfdata_hollis$ jps -v +2679 org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar -Djava.library.path=/usr/lib/jni:/usr/lib/x86_64-linux-gnu/jni -Dosgi.requiredJavaVersion=1.6 -XX:MaxPermSize=256m -Xms40m -Xmx512m +13157 Jps -Denv.class.path=/home/hollis/tools/java/jdk1.7.0_71/lib:/home/hollis/tools/java/jdk1.7.0_71/jre/lib: -Dapplication.home=/home/hollis/tools/java/jdk1.7.0_71 -Xms8m +13083 JpsDemo -Dfile.encoding=UTF-8 +``` +PS:jps命令有个地方很不好,似乎只能显示当前用户的java进程,要显示其他用户的还是只能用unix/linux的`ps`命令。 +jps是我最常用的java命令。使用jps可以查看当前有哪些Java进程处于运行状态。如果我运行了一个web应用(使用tomcat、jboss、jetty等启动)的时候,我就可以使用jps查看启动情况。有的时候我想知道这个应用的日志会输出到哪里,或者启动的时候使用了哪些javaagent,那么我可以使用jps -v 查看进程的jvm参数情况。 + +### JPS失效处理 +现象: 用`ps -ef|grep java`能看到启动的java进程,但是用jps查看却不存在该进程的id。 +待会儿解释过之后就能知道在该情况下,jconsole、jvisualvm可能无法监控该进程,其他java自带工具也可能无法使用 +分析: jps、jconsole、jvisualvm等工具的数据来源就是这个文件(/tmp/hsperfdata_userName/pid)。所以当该文件不存在或是无法读取时就会出现jps无法查看该进程号,jconsole无法监控等问题 +原因: +(1)、磁盘读写、目录权限问题 若该用户没有权限写/tmp目录或是磁盘已满,则无法创建/tmp/hsperfdata_userName/pid文件。或该文件已经生成,但用户没有读权限 +(2)、临时文件丢失,被删除或是定期清理 对于linux机器,一般都会存在定时任务对临时文件夹进行清理,导致/tmp目录被清空。这也是我第一次碰到该现象的原因。常用的可能定时删除临时目录的工具为crontab、redhat的tmpwatch、ubuntu的tmpreaper等等 +这个导致的现象可能会是这样,用jconsole监控进程,发现在某一时段后进程仍然存在,但是却没有监控信息了。 +(3)、java进程信息文件存储地址被设置,不在/tmp目录下 上面我们在介绍时说默认会在/tmp/hsperfdata_userName目录保存进程信息,但由于以上1、2所述原因,可能导致该文件无法生成或是丢失,所以java启动时提供了参数(`-Djava.io.tmpdir`),可以对这个文件的位置进行设置,而jps、jconsole都只会从/tmp目录读取,而无法从设置后的目录读物信息,这是我第二次碰到该现象的原因 + +附: +1.如何给main传递参数 在eclipse中,鼠标右键->Run As->Run COnfiguations->Arguments->在Program arguments中写下要传的参数值 +1.如何给JVM传递参数 在eclipse中,鼠标右键->Run As->Run COnfiguations->Arguments->在VM arguments中写下要传的参数值(一般以-D开头) diff --git "a/01 - JavaSE/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/02 - jstack.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/02 - jstack.md" similarity index 98% rename from "01 - JavaSE/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/02 - jstack.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/02 - jstack.md" index 2ee295c5..147c52a9 100644 --- "a/01 - JavaSE/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/02 - jstack.md" +++ "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/02 - jstack.md" @@ -1,100 +1,100 @@ -### jstack是java虚拟机自带的一种堆栈跟踪工具。 -### 功能 - jstack用于生成java虚拟机当前时刻的线程快照。**线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等**。 - 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 - 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。 - 另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。 - So,**jstack命令主要用来查看Java线程的调用堆栈的,可以用来分析线程问题(如死锁)**。 -### 线程状态 - 想要通过jstack命令来分析线程的情况的话,首先要知道线程都有哪些状态,下面这些状态是我们使用jstack命令查看线程堆栈信息时可能会看到的线程的几种状态: - NEW,未启动的。不会出现在Dump中。 - RUNNABLE,在虚拟机内执行的。 - BLOCKED,受阻塞并等待监视器锁。 - WATING,无限期等待另一个线程执行特定操作。 - TIMED_WATING,有时限的等待另一个线程的特定操作。 - TERMINATED,已退出的。 - Monitor - 在多线程的 JAVA程序中,实现线程之间的同步,就要说说 Monitor。 Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。下 面这个图,描述了线程和 Monitor之间关系,以 及线程的状态转换图: - - 进入区(Entrt Set):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。 - 拥有者(The Owner):表示某一线程成功竞争到对象锁。 - 等待区(Wait Set):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。 - 从图中可以看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是“Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在 “Wait Set”中等待的线程状态是 “in Object.wait()”。 先看 “Entry Set”里面的线程。我们称被 synchronized保护起来的代码段为临界区。当一个线程申请进入临界区时,它就进入了 “Entry Set”队列。对应的 code就像: - synchronized(obj) { - ......... - - } - 调用修饰 - 表示线程在方法调用时,额外的重要的操作。线程Dump分析的重要信息。修饰上方的方法调用。 - ``` - locked <地址> 目标:使用synchronized申请对象锁成功,监视器的拥有者。 - waiting to lock <地址> 目标:使用synchronized申请对象锁未成功,在迚入区等待。 - waiting on <地址> 目标:使用synchronized申请对象锁成功后,释放锁幵在等待区等待。 - parking to wait for <地址> 目标 - ``` - **locked** - ``` - at oracle.jdbc.driver.PhysicalConnection.prepareStatement - - locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection) - at oracle.jdbc.driver.PhysicalConnection.prepareStatement - - locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection) - at com.jiuqi.dna.core.internal.db.datasource.PooledConnection.prepareStatement - ``` - 通过synchronized关键字,成功获取到了对象的锁,成为监视器的拥有者,在临界区内操作。对象锁是可以线程重入的。 - **waiting to lock** - ``` - at com.jiuqi.dna.core.impl.CacheHolder.isVisibleIn(CacheHolder.java:165) - - waiting to lock <0x0000000097ba9aa8> (a CacheHolder) - at com.jiuqi.dna.core.impl.CacheGroup$Index.findHolder - at com.jiuqi.dna.core.impl.ContextImpl.find - at com.jiuqi.dna.bap.basedata.common.util.BaseDataCenter.findInfo - ``` - 通过synchronized关键字,没有获取到了对象的锁,线程在监视器的进入区等待。在调用栈顶出现,线程状态为Blocked。 - **waiting on** - ``` - at java.lang.Object.wait(Native Method) - - waiting on <0x00000000da2defb0> (a WorkingThread) - at com.jiuqi.dna.core.impl.WorkingManager.getWorkToDo - - locked <0x00000000da2defb0> (a WorkingThread) - at com.jiuqi.dna.core.impl.WorkingThread.run - ``` - 通过synchronized关键字,成功获取到了对象的锁后,调用了wait方法,进入对象的等待区等待。在调用栈顶出现,线程状态为WAITING或TIMED_WATING。 - **parking to wait for** - park是基本的线程阻塞原语,不通过监视器在对象上阻塞。随concurrent包会出现的新的机制,不synchronized体系不同。 - 线程动作 - 线程状态产生的原因 - ``` - runnable:状态一般为RUNNABLE。 - in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。 - waiting for monitor entry:进入区等待,状态为BLOCKED。 - waiting on condition:等待区等待、被park。 - sleeping:休眠的线程,调用了Thread.sleep()。 - ``` - **Wait on condition** 该状态出现在线程等待某个条件的发生。具体是什么原因,可以结合 stacktrace来分析。 最常见的情况就是线程处于sleep状态,等待被唤醒。 常见的情况还有等待网络IO:在java引入nio之前,对于每个网络连接,都有一个对应的线程来处理网络的读写操作,即使没有可读写的数据,线程仍然阻塞在读写操作上,这样有可能造成资源浪费,而且给操作系统的线程调度也带来压力。在 NewIO里采用了新的机制,编写的服务器程序的性能和可扩展性都得到提高。 正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几 乎消耗了所有的带宽,仍然有大量数据等待网络读 写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。所以要结合系统的一些性能观察工具来综合分析,比如 netstat统计单位时间的发送包的数目,如果很明显超过了所在网络带宽的限制 ; 观察 cpu的利用率,如果系统态的 CPU时间,相对于用户态的 CPU时间比例较高;如果程序运行在 Solaris 10平台上,可以用 dtrace工具看系统调用的情况,如果观察到 read/write的系统调用的次数或者运行时间遥遥领先;这些都指向由于网络带宽所限导致的网络瓶颈。(来自http://www.blogjava.net/jzone/articles/303979.html) - -### 线程Dump的分析 - **原则** - 结合代码阅读的推理。需要线程Dump和源码的相互推导和印证。 - 造成Bug的根源往往丌会在调用栈上直接体现,一定格外注意线程当前调用之前的所有调用。 -入手点 -**进入区等待** -"d&a-3588" daemon waiting for monitor entry [0x000000006e5d5000] -java.lang.Thread.State: BLOCKED (on object monitor) -at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle() -- waiting to lock <0x0000000602f38e90> (a java.lang.Object) -at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle() -线程状态BLOCKED,线程动作wait on monitor entry,调用修饰waiting to lock总是一起出现。表示在代码级别已经存在冲突的调用。必然有问题的代码,需要尽可能减少其发生。 -**同步块阻塞** -一个线程锁住某对象,大量其他线程在该对象上等待。 -"blocker" runnable -java.lang.Thread.State: RUNNABLE -at com.jiuqi.hcl.javadump.Blocker$1.run(Blocker.java:23) -- locked <0x00000000eb8eff68> (a java.lang.Object) -"blockee-11" waiting for monitor entry -java.lang.Thread.State: BLOCKED (on object monitor) -at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41) -- waiting to lock <0x00000000eb8eff68> (a java.lang.Object) -"blockee-86" waiting for monitor entry -java.lang.Thread.State: BLOCKED (on object monitor) -at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41) -- waiting to lock <0x00000000eb8eff68> (a java.lang.Object) +### jstack是java虚拟机自带的一种堆栈跟踪工具。 +### 功能 + jstack用于生成java虚拟机当前时刻的线程快照。**线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等**。 + 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 + 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。 + 另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。 + So,**jstack命令主要用来查看Java线程的调用堆栈的,可以用来分析线程问题(如死锁)**。 +### 线程状态 + 想要通过jstack命令来分析线程的情况的话,首先要知道线程都有哪些状态,下面这些状态是我们使用jstack命令查看线程堆栈信息时可能会看到的线程的几种状态: + NEW,未启动的。不会出现在Dump中。 + RUNNABLE,在虚拟机内执行的。 + BLOCKED,受阻塞并等待监视器锁。 + WATING,无限期等待另一个线程执行特定操作。 + TIMED_WATING,有时限的等待另一个线程的特定操作。 + TERMINATED,已退出的。 + Monitor + 在多线程的 JAVA程序中,实现线程之间的同步,就要说说 Monitor。 Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。下 面这个图,描述了线程和 Monitor之间关系,以 及线程的状态转换图: + + 进入区(Entrt Set):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。 + 拥有者(The Owner):表示某一线程成功竞争到对象锁。 + 等待区(Wait Set):表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。 + 从图中可以看出,一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是“Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在 “Wait Set”中等待的线程状态是 “in Object.wait()”。 先看 “Entry Set”里面的线程。我们称被 synchronized保护起来的代码段为临界区。当一个线程申请进入临界区时,它就进入了 “Entry Set”队列。对应的 code就像: + synchronized(obj) { + ......... + + } + 调用修饰 + 表示线程在方法调用时,额外的重要的操作。线程Dump分析的重要信息。修饰上方的方法调用。 + ``` + locked <地址> 目标:使用synchronized申请对象锁成功,监视器的拥有者。 + waiting to lock <地址> 目标:使用synchronized申请对象锁未成功,在迚入区等待。 + waiting on <地址> 目标:使用synchronized申请对象锁成功后,释放锁幵在等待区等待。 + parking to wait for <地址> 目标 + ``` + **locked** + ``` + at oracle.jdbc.driver.PhysicalConnection.prepareStatement + - locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection) + at oracle.jdbc.driver.PhysicalConnection.prepareStatement + - locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection) + at com.jiuqi.dna.core.internal.db.datasource.PooledConnection.prepareStatement + ``` + 通过synchronized关键字,成功获取到了对象的锁,成为监视器的拥有者,在临界区内操作。对象锁是可以线程重入的。 + **waiting to lock** + ``` + at com.jiuqi.dna.core.impl.CacheHolder.isVisibleIn(CacheHolder.java:165) + - waiting to lock <0x0000000097ba9aa8> (a CacheHolder) + at com.jiuqi.dna.core.impl.CacheGroup$Index.findHolder + at com.jiuqi.dna.core.impl.ContextImpl.find + at com.jiuqi.dna.bap.basedata.common.util.BaseDataCenter.findInfo + ``` + 通过synchronized关键字,没有获取到了对象的锁,线程在监视器的进入区等待。在调用栈顶出现,线程状态为Blocked。 + **waiting on** + ``` + at java.lang.Object.wait(Native Method) + - waiting on <0x00000000da2defb0> (a WorkingThread) + at com.jiuqi.dna.core.impl.WorkingManager.getWorkToDo + - locked <0x00000000da2defb0> (a WorkingThread) + at com.jiuqi.dna.core.impl.WorkingThread.run + ``` + 通过synchronized关键字,成功获取到了对象的锁后,调用了wait方法,进入对象的等待区等待。在调用栈顶出现,线程状态为WAITING或TIMED_WATING。 + **parking to wait for** + park是基本的线程阻塞原语,不通过监视器在对象上阻塞。随concurrent包会出现的新的机制,不synchronized体系不同。 + 线程动作 + 线程状态产生的原因 + ``` + runnable:状态一般为RUNNABLE。 + in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。 + waiting for monitor entry:进入区等待,状态为BLOCKED。 + waiting on condition:等待区等待、被park。 + sleeping:休眠的线程,调用了Thread.sleep()。 + ``` + **Wait on condition** 该状态出现在线程等待某个条件的发生。具体是什么原因,可以结合 stacktrace来分析。 最常见的情况就是线程处于sleep状态,等待被唤醒。 常见的情况还有等待网络IO:在java引入nio之前,对于每个网络连接,都有一个对应的线程来处理网络的读写操作,即使没有可读写的数据,线程仍然阻塞在读写操作上,这样有可能造成资源浪费,而且给操作系统的线程调度也带来压力。在 NewIO里采用了新的机制,编写的服务器程序的性能和可扩展性都得到提高。 正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几 乎消耗了所有的带宽,仍然有大量数据等待网络读 写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。所以要结合系统的一些性能观察工具来综合分析,比如 netstat统计单位时间的发送包的数目,如果很明显超过了所在网络带宽的限制 ; 观察 cpu的利用率,如果系统态的 CPU时间,相对于用户态的 CPU时间比例较高;如果程序运行在 Solaris 10平台上,可以用 dtrace工具看系统调用的情况,如果观察到 read/write的系统调用的次数或者运行时间遥遥领先;这些都指向由于网络带宽所限导致的网络瓶颈。(来自http://www.blogjava.net/jzone/articles/303979.html) + +### 线程Dump的分析 + **原则** + 结合代码阅读的推理。需要线程Dump和源码的相互推导和印证。 + 造成Bug的根源往往丌会在调用栈上直接体现,一定格外注意线程当前调用之前的所有调用。 +入手点 +**进入区等待** +"d&a-3588" daemon waiting for monitor entry [0x000000006e5d5000] +java.lang.Thread.State: BLOCKED (on object monitor) +at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle() +- waiting to lock <0x0000000602f38e90> (a java.lang.Object) +at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle() +线程状态BLOCKED,线程动作wait on monitor entry,调用修饰waiting to lock总是一起出现。表示在代码级别已经存在冲突的调用。必然有问题的代码,需要尽可能减少其发生。 +**同步块阻塞** +一个线程锁住某对象,大量其他线程在该对象上等待。 +"blocker" runnable +java.lang.Thread.State: RUNNABLE +at com.jiuqi.hcl.javadump.Blocker$1.run(Blocker.java:23) +- locked <0x00000000eb8eff68> (a java.lang.Object) +"blockee-11" waiting for monitor entry +java.lang.Thread.State: BLOCKED (on object monitor) +at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41) +- waiting to lock <0x00000000eb8eff68> (a java.lang.Object) +"blockee-86" waiting for monitor entry +java.lang.Thread.State: BLOCKED (on object monitor) +at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41) +- waiting to lock <0x00000000eb8eff68> (a java.lang.Object) diff --git "a/01 - JavaSE/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/03 - jstat.md" "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/03 - jstat.md" similarity index 99% rename from "01 - JavaSE/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/03 - jstat.md" rename to "01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/03 - jstat.md" index 15786107..ee5b597c 100644 --- "a/01 - JavaSE/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/03 - jstat.md" +++ "b/01 - JavaSE Java\346\240\270\345\277\203/01 - JVM/JVM\345\270\270\350\247\201\345\221\275\344\273\244/03 - jstat.md" @@ -1,57 +1,57 @@ -jstat(JVM Statistics Monitoring Tool)是 **用于监控虚拟机各种运行状态信息的命令行工具**。 -他可以 **显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据**,在没有GUI图形的服务器上,它是运行期定位虚拟机性能问题的首选工具。 -jstat位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。 -可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。 -jstat 命令格式 - **jstat -