-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
158 lines (95 loc) · 113 KB
/
Copy pathatom.xml
File metadata and controls
158 lines (95 loc) · 113 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Jason's Blog</title>
<subtitle>Jason</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://www.jmzhang.com/"/>
<updated>2018-10-09T05:12:59.112Z</updated>
<id>http://www.jmzhang.com/</id>
<author>
<name>JasonZhang</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>git学习笔记</title>
<link href="http://www.jmzhang.com/2018/10/09/git%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
<id>http://www.jmzhang.com/2018/10/09/git学习笔记/</id>
<published>2018-10-09T13:10:43.000Z</published>
<updated>2018-10-09T05:12:59.112Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><a id="more"></a><p><img src="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy1.png" alt="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy1.png"></p><p><strong>前言</strong></p><p>什么是Git?<br>Git是目前世界上最先进的分布式版本控制系统(没有之一),而且是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何项目。</p><p><strong>Git安装</strong></p><p>在<strong>Debian</strong>或者<strong>Ubuntu Linux</strong>下的Git安装非常简单,直接一条命令搞定</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">| sudo apt-<span class="builtin-name">get</span> install git</span><br></pre></td></tr></table></figure><p><strong>Windows</strong>下的模拟环境安装起来比较复杂,那么可以用牛人封装好的模拟环境加Git,叫<strong>msysgit</strong>,只需要下载一个exe然后双击安装 可从<code><https://git-for-windows.github.io/></code>下载,或者从<a href="https://pan.baidu.com/s/1kU5OCOB#list/path=%2Fpub%2Fgit" target="_blank" rel="noopener">廖雪峰老师的镜像</a>下载,然后按默认选项安装 .安装完成后,在开始菜单里找到“Git”->“GitBash”,跳出一个类似命令行窗口的东西,就说明Git安装成功</p><p>成功安装之后,还需要配置一下全局个人信息:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git<span class="built_in"> config </span>--global user.name <span class="string">"Your Name"</span></span><br><span class="line">git<span class="built_in"> config </span>--global user.email <span class="string">"email@example.com"</span></span><br></pre></td></tr></table></figure><p>每次提交,都会记录这两个值,<code>--global</code>参数,表示你这台机器上所有的Git仓库都会使用这个配置<br>可使用<code>git config -l</code> 查看全局配置信息</p><p><strong>运行前配置</strong></p><p>一般在新的系统上,我们都需要先配置下自己的 Git<br>工作环境。配置工作只需一次,以后升级时还会沿用现在的配置。</p><p><strong>配置文件如何生效</strong></p><p>对于 Git 来说,配置文件的权重是<strong>仓库>全局>系统</strong>。Git会使用这一系列的配置文件来存储你定义的偏好,它首先会查找<code>/etc/gitconfig</code>文件(系统级),该文件含有对系统上所有用户及他们所拥有的仓库都生效的配置值。接下来Git 会查找每个用户的<code>\~/.gitconfig</code>文件(全局级)。最后 Git会查找由用户定义的各个库中Git目录下的配置文件<code>.git/config(仓库级)</code>,该文件中的值只对当前所属仓库有效。以上阐述的三层配置从一般到特殊层层推进,如果定义的值有冲突,以后面层中定义的为准,例如:<code>.git/config</code>和<code>/etc/gitconfig</code>的较量中,<code>.git/config</code>取得了胜利。</p><p><strong>查看配置</strong></p><p>格式:<code>git config [--local\|--global\|--system] -l</code></p><p>example:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看当前生效的配置</span></span><br><span class="line">git<span class="built_in"> config </span>-l</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看仓库级的配置</span></span><br><span class="line">git<span class="built_in"> config </span>--local -l</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看全局级的配置</span></span><br><span class="line">git<span class="built_in"> config </span>--global -l</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看系统级的配置</span></span><br><span class="line">git<span class="built_in"> config </span>--system -l</span><br></pre></td></tr></table></figure><p><strong>修改配置</strong></p><p>格式:<code>git config [--local\|--global\|--system] key value</code></p><p>example:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">| git<span class="built_in"> config </span>--global user.name ybd</span><br><span class="line">| git<span class="built_in"> config </span>--global user.email yangbingdong1994@gmail.com</span><br></pre></td></tr></table></figure><p><strong>创建仓库(Repository)</strong></p><p>创建一个目录并进入,进行初始化仓库<br><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">| mkdir repo </span></span><br><span class="line"><span class="string">| cd repo </span></span><br><span class="line"><span class="string">| git init</span></span><br></pre></td></tr></table></figure></p><p>目录下会多一个<code>.git</code> 的隐藏文件,现在要创建一个文件并提交到仓库<br><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">| touch read</span><br><span class="line">| vi read</span><br><span class="line">| # 按a进入编辑</span><br><span class="line">| # 输入Git is a distributed version control system</span><br><span class="line">| # 按下Esc,并输入 <span class="string">":wq"</span> 保存退出</span><br><span class="line">| git <span class="builtin-name">add</span> README.md #添加文件到缓存区</span><br><span class="line">| git commit -m <span class="string">"first commit"</span> #将缓存区的文件提交到本地仓库</span><br></pre></td></tr></table></figure></p><p>多个文件提交可用<code>git add -A</code>然后再<code>commit</code><br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">| ➜ repo git:(master) ✗ git <span class="keyword">commit</span> -m <span class="string">"first commit"</span> </span><br><span class="line">| [<span class="keyword">master</span> (根提交) <span class="number">201817</span>f5] <span class="keyword">first</span> <span class="keyword">commit</span> </span><br><span class="line">| <span class="number">1</span> <span class="keyword">file</span> <span class="keyword">changed</span>, <span class="number">2</span> insertions(+) </span><br><span class="line">| <span class="keyword">create</span> <span class="keyword">mode</span> <span class="number">105624</span> <span class="keyword">read</span></span><br></pre></td></tr></table></figure></p><p><strong>操作的自由穿越</strong></p><p>要随时掌握工作区的状态:<code>git status</code><br>查看修改内容:<code>git diff read</code><br>查看版本历史信息 <code>got log</code> 或<code>git log --pretty=oneline</code></p><p><strong>版本穿越</strong></p><p>退到上一个版本:</p><table><thead><tr><th>git reset –hard HEAD^</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>上上一个版本就是 <code>HEAD^</code>,当然往上100个版本写100个^比较容易数不过来,所以写成 HEAD~100<br>要重返未来,查看命令历史:<code>git reflog</code></p><p><strong>修改管理</strong></p><p>添加文件到缓存区:<code>git add read</code>或 <code>git add -A</code><br>然后提交:<code>git commit -m "msg"</code><br>查看状态:<code>git status</code><br><strong>每次修改,如果不<code>add</code>到暂存区,那就不会加入到<code>commit</code>中</strong></p><p><strong>撤销修改</strong></p><p>当你发现工作区的修改有错误的时候,可丢弃工作区的修改:</p><table><thead><tr><th>git checkout – read</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>命令 <code>git checkout --read</code>意思就是,把 read 文件在工作区的修改全部撤销,这里有两种情况:</p><p>一种是<code>read</code> 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态</p><p>一种是 <code>read</code> 已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态</p><p><strong>总之,就是让这个文件回到最近一次 <code>git commit</code> 或 <code>git add</code> 时的状态</strong><br><strong>注意!<code>git checkout -- file</code> 命令中的 <code>--</code>很重要,没有<code>--</code> 就变成了切换分支了</strong></p><p>当你发现该文件修改错误并且已经提交到了缓存区,这个时候可以把暂存区的修改撤销掉(unstage),重新放回工作区:</p><table><thead><tr><th>git reset HEAD read</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>然后再丢弃工作区中的修改:</p><table><thead><tr><th>git checkout – read</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p><code>git reset</code>命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本</p><p><strong>删除文件</strong></p><p>如果把工作区中的文件删除了,那么工作区和版本库就不一致,<code>git status</code>命令会立刻告诉你哪些文件被删除了<br>现在有两个选择</p><ul><li><p>一是确实要从版本库中删除该文件,那就用命令删掉,并且提交:</p><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">| git rm read </span></span><br><span class="line"><span class="string">| git commit -m "</span>delete<span class="string">"</span></span><br></pre></td></tr></table></figure></li><li><p>另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:</p><p>| git checkout – read |<br>|———————-|</p></li></ul><p><code>git checkout</code>其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”</p><p><strong>远程仓库</strong></p><p>那么学会了Git的基本操作之后,对于分布式管理我们还需要有一个远程仓库供大家一起共同开发,好在有一个全世界最大最神奇的同性交友网—— <a href="https://github.com/" target="_blank" rel="noopener">Github</a><br>那么在使用Github之前呢,我们需要设置一下与Github的SSH通讯: </p><ol><li>创建SSH Key(已有.ssh目录的可以略过)</li></ol><table><thead><tr><th>ssh-keygen -t rsa -C “youremail\@example.com”</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码<br>如果一切顺利的话,可以在用户主目录里找到<code>.ssh</code> 目录,里面有 <code>id_rsa</code> 和 <code>id_rsa.pub</code> 两个文件,这两个就是<code>SSH Key</code>的秘钥对,<code>id_rsa</code>是私钥,不能泄露出去,<code>id_rsa.pub</code>是公钥,可以放心地告诉任何人</p><ol start="2"><li>登陆<code>GitHub</code>,打开<code>“Account settings”</code>,<code>“SSH Keys”</code>页面,然后,点<code>“Add SSHKey”</code>,填上任意Title,在Key文本框里粘贴<code>id_rsa.pub</code>文件的内容,最后点<code>“Add Key”</code></li></ol><p><strong>添加远程仓库</strong></p><p>首先到Github创建一个仓库<br>然后与本地关联:</p><table><thead><tr><th>git remote add origin git\@github.com:your-name/repo-name.git</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>远程库的名字就是<code>origin</code>,这是Git默认的叫法,也可以改成别的,但是<code>origin</code>这个名字一看就知道是远程库</p><p>下一步,就可以把本地库的所有内容推送到远程库上:</p><table><thead><tr><th>git push -u origin master</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>把本地库的内容推送到远程,用 <code>git push</code> 命令,实际上是把当前分支<code>master</code>推送到远程<br>由于远程库是空的,我们第一次推送<code>master</code>分支时,加上了 -u 参数,Git不但会把本地的<code>master</code>分支内容推送的远程新的<code>master</code>分支,还会把本地的<code>master</code>分支和远程的<code>master</code>分支关联起来,在以后的推送或者拉取时就可以简化命令</p><p>此后的推送都可以使用:</p><table><thead><tr><th>git push</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p><strong>从远程仓库克隆</strong></p><table><thead><tr><th>git git\@github.com:your-name/repo-name.git</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p><strong>标签管理</strong></p><p><strong>查看tag</strong></p><p>列出所有<code>tag</code>:</p><table><thead><tr><th>git tag</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>这样列出的tag是按字母排序的,和创建时间没关系。如果只是想查看某些<code>tag</code>的话,可以加限定:</p><table><thead><tr><th>git tag -l v1.*</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>这样就只会列出<code>1.X</code>的版本。</p><p><strong>创建tag</strong></p><p>创建轻量级<code>tag</code>:</p><table><thead><tr><th>git tag 1.0.1</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>这样创建的<code>tag</code>没有附带其他信息,与之相应的是带信息的<code>tag</code>,<code>-m</code>后面带的就是注释信息,这样在日后查看的时候会很有用,这种是普通<code>tag</code>,还有一种有签名的<code>tag</code>:</p><table><thead><tr><th>git tag -a 1.0.1 -m ‘first version’</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>除了可以为当前的进度添加<code>tag</code>,我们还可以为以前的<code>commit</code>添加<code>tag</code>:<br>首先查看以前的<code>commit</code></p><table><thead><tr><th>git log –oneline</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>假如有这样一个<code>commit</code>:a5cbc2 updated readme<br>这样为他添加tag</p><table><thead><tr><th>git tag -a v1.1 a5cbc2</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p><strong>删除tag</strong></p><p>很简单,知道<code>tag</code>名称后:</p><table><thead><tr><th>git tag -d v1.0</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>删除远程分支:</p><table><thead><tr><th>git push origin –delete tag \<tagname></th></tr></thead><tbody><tr><td></td></tr></tbody></table><p><strong>共享tag</strong></p><p>我们在执行git<br><code>push</code>的时候,tag是不会上传到服务器的,比如现在的github,创建<code>tag</code>后<code>git</code><br><code>push</code>,在github网页上是看不到<code>tag</code>的,为了共享这些<code>tag</code>,你必须这样:</p><table><thead><tr><th>git push origin –tags</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p><strong>分支管理</strong></p><p>分支相当与平行宇宙,互不干扰,哪天合并了就拥有了所有平行宇宙的特性 </p><p><img src="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy2.png" alt="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy2.png"></p><p><strong>创建与合并分支</strong></p><ul><li><p>每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即<code>master</code>分支</p></li><li><p>一开始的时候,<code>master</code>分支是一条线,Git用 <code>master</code>指向最新的提交,再用<code>HEAD</code>指向<code>master</code> ,就能确定当前分支,以及当前分支的提交点</p></li><li><p>当我们创建新的分支,例如<code>dev</code> 时,Git新建了一个指针叫 <code>dev</code> ,指向 <code>master</code> 相同的提交,再把 <code>HEAD</code> 指向<code>dev</code> ,就表示当前分支在<code>dev</code> 上</p></li><li><p>Git创建一个分支很快,因为除了增加一个 <code>dev</code>指针,改改<code>HEAD</code>的指向,工作区的文件都没有任何变化</p></li><li><p>当 <code>HEAD</code>指向<code>dev</code> ,对工作区的修改和提交就是针对<code>dev</code>分支了,比如新提交一次后,<code>dev</code>指针往前移动一步,而 <code>master</code>指针不变 </p></li></ul><pre><code></code></pre><p>查看分支:<code>git branch</code><br>创建分支:<code>git branch \<name\></code><br>切换分支:<code>git checkout \<name\></code><br>创建+切换分支:<code>git checkout -b \<name\></code><br>合并某分支到当前分支:<code>git merge \<name\></code><br>删除分支:<code>git branch -d \<name\></code></p><p><strong>解决冲突</strong></p><p>合并分支并不是每次都不会出问题,如不同的分支对同一个文件同一行都被修改过,就会出现以下情况 </p><p><img src="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy4.png" alt="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy4.png"></p><p>那么再次合并有可能会冲突</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">➜ repo git:(master) git <span class="keyword">merge</span> feature1 </span><br><span class="line">自动合并 <span class="keyword">read</span></span><br><span class="line">冲突(内容):合并冲突于 <span class="keyword">read</span></span><br><span class="line">自动合并失败,修正冲突然后提交修正的结果。</span><br><span class="line">➜ repo git:(<span class="keyword">master</span>) ✗ git <span class="keyword">status</span> </span><br><span class="line">位于分支 <span class="keyword">master</span></span><br><span class="line">您有尚未合并的路径。</span><br><span class="line"> (解决冲突并运行 <span class="string">"git commit"</span>)</span><br><span class="line"></span><br><span class="line">未合并的路径:</span><br><span class="line"> (使用 <span class="string">"git add <文件>..."</span> 标记解决方案)</span><br><span class="line"></span><br><span class="line">双方修改: <span class="keyword">read</span></span><br><span class="line"></span><br><span class="line">修改尚未加入提交(使用 <span class="string">"git add"</span> 和/或 <span class="string">"git commit -a"</span>)</span><br></pre></td></tr></table></figure><p>这种情况必须手动解决然后再次<code>git add</code>.,<code>git commit -m "commit"</code>,打开文件可看到</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Git is a version control</span><br><span class="line"><<<<<<< HEAD</span><br><span class="line">Creating a new branch is quick & simple.</span><br><span class="line">=======</span><br><span class="line">Creating a new branch is quick AND simple.</span><br><span class="line">>>>>>>> feature1</span><br></pre></td></tr></table></figure><p>Git用<code><<<<<<<</code>,<code>=======</code>,<code>>>>>>>></code>标记出不同分支的内容,那么经过合意,不好意思,大师兄说了,在座的各位都是垃圾,于是改成</p><table><thead><tr><th>Git,too fast too simple</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>再提交<br><figure class="highlight gherkin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">|<span class="string"> 1 </span>|<span class="string"> ➜ repo git:(master) ✗ git add read </span>|</span><br><span class="line">|<span class="string"> 2 </span>|<span class="string"> ➜ repo git:(master) ✗ git commit -m "conflict fixed" </span>|</span><br><span class="line">|<span class="string"> 3 </span>|<span class="string"> [master 8933f88] conflict fixed </span>|</span><br><span class="line">|<span class="string"> 4 </span>|<span class="string"> ➜ repo git:(master) </span>|</span><br></pre></td></tr></table></figure></p><p>ok了,再次<code>add</code>和 <code>commit</code> ,现在<code>master</code>分支和<code>feature1</code>分支变成了这样 </p><p><img src="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy5.png" alt="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy5.png"></p><p><strong>多PC协同开发</strong></p><p>当你从远程仓库克隆时,实际上Git自动把本地的 <code>master</code>分支和远程的<code>master</code>分支对应起来了,并且,远程仓库的默认名称是<code>origin</code></p><p>查看远程库的信息:<br>查看简单信息:<code>git remote</code><br>查看详细信息:<code>git remote -v</code><br>查看远程仓库分支:<code>git branch -r</code><br>查看本地分支与远程分支的对应关系:<code>git branch -vv</code></p><p>推送分支<br><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git push origin <branch> </span><br><span class="line"></span><br><span class="line">git push -u origin <branch> # 第一次推送加-u可以把当前分支与远程分支关联起来</span><br></pre></td></tr></table></figure></p><p>克隆分支并关联<br><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">git clone git@github.com:youName/program.git # 默认克隆master分支到当前目录(包含分支文件目录)</span><br><span class="line"></span><br><span class="line">git clone -b <branch> git@github.com:youName/program.git ./</span><br><span class="line"># 克隆指定分支到指定文件目录下(不包含分支文件目录)</span><br></pre></td></tr></table></figure></p><p>创建远程<code>origin</code>的<code>dev</code> 分支到本地</p><table><thead><tr><th>git checkout -b <branch> origin/<branch></branch></branch></th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>关联本地分支与远程仓库分支</p><table><thead><tr><th>git branch –set-upstream <branch> origin/<branch></branch></branch></th></tr></thead><tbody><tr><td></td></tr></tbody></table><p><strong>同步更新Github Fork的项目</strong></p><p>1、<code>fork</code>项目并<code>clone</code>到本地</p><p>2、进入项目根目录</p><p>3、添加<code>remote</code>指向<strong>上游仓库</strong></p><table><thead><tr><th>git remote add upstream <a href="https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git" target="_blank" rel="noopener">https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git</a></th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>4、把上游项目<code>fetch</code>下来</p><table><thead><tr><th>git fetch upstream</th></tr></thead><tbody><tr><td></td></tr></tbody></table><p>5、<code>merge</code>到<code>master</code><br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">| git checkout master </span><br><span class="line">| git <span class="keyword">merge</span> upstream/<span class="keyword">master</span></span><br></pre></td></tr></table></figure></p><p>6、<code>push</code>到自己的远程仓库,搞定~</p><p><strong>最后</strong></p><p>Git真的异常强大,但命令繁多,需多加练习</p><p><em>参考:</em><a href="http://www.liaoxuefeng.com/" target="_blank" rel="noopener">廖雪峰老师的教程</a></p><h2 id="附命令图"><a href="#附命令图" class="headerlink" title="附命令图"></a><strong>附命令图</strong></h2><p><img src="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy0.png" alt="http://mdpost.jmzhang.top/mdpost/20181009/gitstudy0.png"></p>]]></content>
<summary type="html">
git学习笔记.
</summary>
<category term="git" scheme="http://www.jmzhang.com/categories/git/"/>
<category term="git" scheme="http://www.jmzhang.com/tags/git/"/>
</entry>
<entry>
<title>常用的八种排序算法Java代码实现</title>
<link href="http://www.jmzhang.com/2018/09/06/%E5%B8%B8%E7%94%A8%E7%9A%84%E5%85%AB%E7%A7%8D%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95Java%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0/"/>
<id>http://www.jmzhang.com/2018/09/06/常用的八种排序算法Java代码实现/</id>
<published>2018-09-05T21:34:53.000Z</published>
<updated>2018-09-12T15:05:31.300Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p>Algorithm<br><a id="more"></a></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> algorithm;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Arrays;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EightAlgorithm</span> </span>{</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * 常用的八种排序算法Java代码实现</span></span><br><span class="line"><span class="comment"> * 时间:2018-9-5-下午9:14:30 </span></span><br><span class="line"><span class="comment"> * 邮件:hasp_Jason@163.com</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@exception</span> </span></span><br><span class="line"><span class="comment"> * *辅助记忆*</span></span><br><span class="line"><span class="comment"> * 时间复杂度记忆- </span></span><br><span class="line"><span class="comment"> * 冒泡、选择、直接 排序需要两个for循环,每次只关注一个元素,平均时间复杂度为O(n2)(一遍找元素O(n),一遍找位置O(n))</span></span><br><span class="line"><span class="comment"> * 快速、归并、希尔、堆基于二分思想,log以2为底,平均时间复杂度为O(nlogn)(一遍找元素O(n),一遍找位置O(logn))</span></span><br><span class="line"><span class="comment"> * 稳定性记忆-“快选希堆”(非稳定:快牺牲稳定性) </span></span><br><span class="line"><span class="comment"> * 排序算法的稳定性:排序前后相同元素的相对位置不变,则称排序算法是稳定的;否则排序算法是不稳定的。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> []array={<span class="number">23</span>,<span class="number">56</span>,<span class="number">8</span>,<span class="number">45</span>,<span class="number">2</span>,<span class="number">95</span>,<span class="number">11</span>,<span class="number">12</span>,<span class="number">17</span>,<span class="number">10</span>,<span class="number">11</span>};</span><br><span class="line">System.out.println(<span class="string">"length: "</span>+array.length);</span><br><span class="line">insertSort(array);<span class="comment">//1.直接插入</span></span><br><span class="line"><span class="comment">//sheelSort(array);//2.希尔排序</span></span><br><span class="line"><span class="comment">//selectSort(array);//3.简单选择排序</span></span><br><span class="line"><span class="comment">//heapSort(array);//4.堆排序</span></span><br><span class="line"><span class="comment">//bubbleSort(array);//5.冒泡排序</span></span><br><span class="line"><span class="comment">//quickSort(array, 0, array.length-1);//6.快速排序 </span></span><br><span class="line"><span class="comment">//mergeSort(array);//7.归并排序</span></span><br><span class="line"><span class="comment">//sort(array,10);//8.基数排序</span></span><br><span class="line">System.out.println(Arrays.toString(array));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 1.直接插入 经常碰到这样一类排序问题:把新的数据插入到已经排好的数据列中。</span></span><br><span class="line"><span class="comment"> * 平均时间复杂度最坏时间复杂度空间复杂度是否稳定</span></span><br><span class="line"><span class="comment"> * O(n^2)O(n^2)O(1)是</span></span><br><span class="line"><span class="comment"> * 将第一个数和第二个数排序,然后构成一个有序序列</span></span><br><span class="line"><span class="comment"> * 将第三个数插入进去,构成一个新的有序序列。</span></span><br><span class="line"><span class="comment"> * 对第四个数、第五个数……直到最后一个数,重复第二步。</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> ***如何写成代码:</span></span><br><span class="line"><span class="comment"> *1.首先设定插入次数,即循环次数,for(int i=1;i<length;i++),1个数的那次不用插入。</span></span><br><span class="line"><span class="comment"> *2.设定插入数和得到已经排好序列的最后一个数的位数。insertNum和j=i-1。</span></span><br><span class="line"><span class="comment"> *3.从最后一个数开始向前循环,如果插入数小于当前数,就将当前数向后移动一位。</span></span><br><span class="line"><span class="comment"> *4.将当前数放置到空着的位置,即j+1。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">insertSort</span><span class="params">(<span class="keyword">int</span>[] a)</span> </span>{</span><br><span class="line"><span class="keyword">int</span> insertNum; <span class="comment">// 要插入的数</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i < a.length; i++) {</span><br><span class="line">insertNum = a[i];</span><br><span class="line"><span class="keyword">int</span> j = i - <span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span> (j >= <span class="number">0</span> && a[j] > insertNum) {<span class="comment">// 将大于insertNum的数向后移动一格</span></span><br><span class="line">a[j + <span class="number">1</span>] = a[j];</span><br><span class="line">j--;</span><br><span class="line">}</span><br><span class="line">a[j + <span class="number">1</span>] = insertNum;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 2.希尔排序 对于直接插入排序问题,数据量巨大时。</span></span><br><span class="line"><span class="comment"> * 平均时间复杂度最坏时间复杂度空间复杂度是否稳定</span></span><br><span class="line"><span class="comment"> * O(nlogn)O(n^s)O(1)不是</span></span><br><span class="line"><span class="comment"> * 将数的个数设为n,取奇数k=n/2,将下标差值为k的数分为一组,构成有序序列。</span></span><br><span class="line"><span class="comment"> * 再取k=k/2 ,将下标差值为k的数分为一组,构成有序序列。</span></span><br><span class="line"><span class="comment"> * 重复第二步,直到k=1执行简单插入排序。</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> ***如何写成代码:</span></span><br><span class="line"><span class="comment"> *1.首先确定分的组数。</span></span><br><span class="line"><span class="comment"> *2.然后对组中元素进行插入排序。</span></span><br><span class="line"><span class="comment"> *3.然后将length/2,重复1,2步,直到length=0为止。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">sheelSort</span><span class="params">(<span class="keyword">int</span>[] a)</span> </span>{</span><br><span class="line"><span class="keyword">int</span> length = a.length;</span><br><span class="line"><span class="keyword">while</span> (length != <span class="number">0</span>) {</span><br><span class="line">length = length / <span class="number">2</span>;</span><br><span class="line">System.out.println(<span class="string">"length变化: "</span> + length);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> x = <span class="number">0</span>; x < length; x++) { <span class="comment">// 分组个数</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = x + length; i < a.length; i += length) {</span><br><span class="line"><span class="keyword">int</span> j = i - length; <span class="comment">// j为有序序列最后一位的位数</span></span><br><span class="line"><span class="keyword">int</span> insertNum = a[i]; <span class="comment">// 要插入的元素</span></span><br><span class="line"><span class="keyword">for</span> (; j >= <span class="number">0</span> && insertNum < a[j]; j -= length) {</span><br><span class="line">a[j + length] = a[j];<span class="comment">// 向后移动length位</span></span><br><span class="line">}</span><br><span class="line">a[j + length] = insertNum;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 3.简单选择排序 常用于取序列中最大最小的几个数时。</span></span><br><span class="line"><span class="comment"> * 平均时间复杂度最坏时间复杂度空间复杂度是否稳定</span></span><br><span class="line"><span class="comment"> * O(n^2) O(n^2)O(1)不是</span></span><br><span class="line"><span class="comment"> * (如果每次比较都交换,那么就是交换排序;如果每次比较完一个循环再交换,就是简单选择排序。)</span></span><br><span class="line"><span class="comment"> * 遍历整个序列,将最小的数放在最前面。</span></span><br><span class="line"><span class="comment"> * 遍历剩下的序列,将最小的数放在最前面。</span></span><br><span class="line"><span class="comment"> * 重复第二步,直到只剩下一个数。</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> ***如何写成代码:</span></span><br><span class="line"><span class="comment"> *1.首先确定循环次数,并且记住当前数字和当前位置。</span></span><br><span class="line"><span class="comment"> *2.将当前位置后面所有的数与当前数字进行对比,小数赋值给key,并记住小数的位置。</span></span><br><span class="line"><span class="comment"> *3.比对完成后,将最小的值与第一个数的值交换。</span></span><br><span class="line"><span class="comment"> *4.重复2、3步。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">selectSort</span><span class="params">(<span class="keyword">int</span>[] a)</span> </span>{</span><br><span class="line"><span class="keyword">int</span> length = a.length;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < length; i++) {<span class="comment">// 循环次数</span></span><br><span class="line"><span class="keyword">int</span> key = a[i];</span><br><span class="line"><span class="keyword">int</span> position = i;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = i + <span class="number">1</span>; j < length; j++) {<span class="comment">// 选出最小值和位置</span></span><br><span class="line"><span class="keyword">if</span> (a[j] < key) {</span><br><span class="line">key = a[j];</span><br><span class="line">position = j;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">a[position] = a[i];<span class="comment">// 交换位置</span></span><br><span class="line">a[i] = key;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 4.堆排序 对简单选择排序的优化。</span></span><br><span class="line"><span class="comment"> * 平均时间复杂度最坏时间复杂度空间复杂度是否稳定</span></span><br><span class="line"><span class="comment"> * O(nlogn)O(nlogn)O(1)不是</span></span><br><span class="line"><span class="comment"> *将序列构建成大顶堆。</span></span><br><span class="line"><span class="comment"> *将根节点与最后一个节点交换,然后断开最后一个节点。</span></span><br><span class="line"><span class="comment"> *重复第一、二步,直到所有节点断开。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">heapSort</span><span class="params">(<span class="keyword">int</span>[] a)</span> </span>{</span><br><span class="line">System.out.println(<span class="string">"开始排序"</span>);</span><br><span class="line"><span class="keyword">int</span> arrayLength = a.length;</span><br><span class="line"><span class="comment">// 循环建堆</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < arrayLength - <span class="number">1</span>; i++) {</span><br><span class="line"><span class="comment">// 建堆</span></span><br><span class="line">buildMaxHeap(a, arrayLength - <span class="number">1</span> - i);</span><br><span class="line"><span class="comment">// 交换堆顶和最后一个元素</span></span><br><span class="line">swap(a, <span class="number">0</span>, arrayLength - <span class="number">1</span> - i);</span><br><span class="line">System.out.println(Arrays.toString(a));</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">swap</span><span class="params">(<span class="keyword">int</span>[] data, <span class="keyword">int</span> i, <span class="keyword">int</span> j)</span> </span>{</span><br><span class="line"><span class="keyword">int</span> tmp = data[i];</span><br><span class="line">data[i] = data[j];</span><br><span class="line">data[j] = tmp;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 对data数组从0到lastIndex建大顶堆</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">buildMaxHeap</span><span class="params">(<span class="keyword">int</span>[] data, <span class="keyword">int</span> lastIndex)</span> </span>{</span><br><span class="line"><span class="comment">// 从lastIndex处节点(最后一个节点)的父节点开始</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = (lastIndex - <span class="number">1</span>) / <span class="number">2</span>; i >= <span class="number">0</span>; i--) {</span><br><span class="line"><span class="comment">// k保存正在判断的节点</span></span><br><span class="line"><span class="keyword">int</span> k = i;</span><br><span class="line"><span class="comment">// 如果当前k节点的子节点存在</span></span><br><span class="line"><span class="keyword">while</span> (k * <span class="number">2</span> + <span class="number">1</span> <= lastIndex) {</span><br><span class="line"><span class="comment">// k节点的左子节点的索引</span></span><br><span class="line"><span class="keyword">int</span> biggerIndex = <span class="number">2</span> * k + <span class="number">1</span>;</span><br><span class="line"><span class="comment">// 如果biggerIndex小于lastIndex,即biggerIndex+1代表的k节点的右子节点存在</span></span><br><span class="line"><span class="keyword">if</span> (biggerIndex < lastIndex) {</span><br><span class="line"><span class="comment">// 若果右子节点的值较大</span></span><br><span class="line"><span class="keyword">if</span> (data[biggerIndex] < data[biggerIndex + <span class="number">1</span>]) {</span><br><span class="line"><span class="comment">// biggerIndex总是记录较大子节点的索引</span></span><br><span class="line">biggerIndex++;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 如果k节点的值小于其较大的子节点的值</span></span><br><span class="line"><span class="keyword">if</span> (data[k] < data[biggerIndex]) {</span><br><span class="line"><span class="comment">// 交换他们</span></span><br><span class="line">swap(data, k, biggerIndex);</span><br><span class="line"><span class="comment">// 将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值</span></span><br><span class="line">k = biggerIndex;</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 5.冒泡排序 一般不用。</span></span><br><span class="line"><span class="comment"> * 平均时间复杂度最坏时间复杂度空间复杂度是否稳定</span></span><br><span class="line"><span class="comment"> * O(n^2) O(n^2)O(1)是</span></span><br><span class="line"><span class="comment"> *将序列中所有元素两两比较,将最大的放在最后面。</span></span><br><span class="line"><span class="comment"> *将剩余序列中所有元素两两比较,将最大的放在最后面。</span></span><br><span class="line"><span class="comment"> *重复第二步,直到只剩下一个数。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> ***如何写成代码:</span></span><br><span class="line"><span class="comment"> *1.设置循环次数。</span></span><br><span class="line"><span class="comment"> *2.设置开始比较的位数,和结束的位数。</span></span><br><span class="line"><span class="comment"> *3.两两比较,将最小的放到前面去。</span></span><br><span class="line"><span class="comment"> *4.重复2、3步,直到循环次数完毕。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">bubbleSort</span><span class="params">(<span class="keyword">int</span>[] a)</span> </span>{</span><br><span class="line"><span class="keyword">int</span> length = a.length;</span><br><span class="line"><span class="keyword">int</span> temp;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < length; i++) {</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j < length - i - <span class="number">1</span>; j++) {</span><br><span class="line"><span class="keyword">if</span> (a[j] > a[j + <span class="number">1</span>]) {</span><br><span class="line">temp = a[j];</span><br><span class="line">a[j] = a[j + <span class="number">1</span>];</span><br><span class="line">a[j + <span class="number">1</span>] = temp;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 6.快速排序要求时间最快时。</span></span><br><span class="line"><span class="comment"> * 平均时间复杂度最坏时间复杂度空间复杂度是否稳定</span></span><br><span class="line"><span class="comment"> * O(nlogn) O(n^2)O(logn)不是</span></span><br><span class="line"><span class="comment"> *选择第一个数为p,小于p的数放在左边,大于p的数放在右边。</span></span><br><span class="line"><span class="comment"> *递归的将p左边和右边的数都按照第一步进行,直到不能递归。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">quickSort</span><span class="params">(<span class="keyword">int</span>[] numbers, <span class="keyword">int</span> start, <span class="keyword">int</span> end)</span> </span>{</span><br><span class="line"><span class="keyword">if</span> (start < end) {</span><br><span class="line"><span class="keyword">int</span> base = numbers[start];<span class="comment">// 选定的基准值</span></span><br><span class="line"><span class="keyword">int</span> temp;</span><br><span class="line"><span class="keyword">int</span> i = start, j = end;</span><br><span class="line"><span class="keyword">do</span> {</span><br><span class="line"><span class="keyword">while</span> ((numbers[i] < base) && (i < end))</span><br><span class="line">i++;</span><br><span class="line"><span class="keyword">while</span> ((numbers[j] > base) && (j > start))</span><br><span class="line">j--;</span><br><span class="line"><span class="keyword">if</span> (i <= j) {</span><br><span class="line">temp = numbers[i];</span><br><span class="line">numbers[i] = numbers[j];</span><br><span class="line">numbers[j] = temp;</span><br><span class="line">i++;</span><br><span class="line">j--;</span><br><span class="line">}</span><br><span class="line">} <span class="keyword">while</span> (i <= j);</span><br><span class="line"><span class="keyword">if</span> (start < j)</span><br><span class="line">quickSort(numbers, start, j);</span><br><span class="line"><span class="keyword">if</span> (end > i)</span><br><span class="line">quickSort(numbers, i, end);</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 7.归并排序速度仅次于快排,内存少的时候使用,可以进行并行计算的时候使用。</span></span><br><span class="line"><span class="comment"> * 平均时间复杂度最坏时间复杂度空间复杂度是否稳定</span></span><br><span class="line"><span class="comment"> * O(nlogn) O(nlogn)O(n)是</span></span><br><span class="line"><span class="comment"> *选择相邻两个数组成一个有序序列。</span></span><br><span class="line"><span class="comment"> *选择相邻的两个有序序列组成一个有序序列。</span></span><br><span class="line"><span class="comment"> *重复第二步,直到全部组成一个有序序列。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">mergeSort</span><span class="params">(<span class="keyword">int</span>[] arr)</span> </span>{</span><br><span class="line"><span class="keyword">int</span>[] temp = <span class="keyword">new</span> <span class="keyword">int</span>[arr.length];<span class="comment">// 在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间</span></span><br><span class="line">mergeSort(arr, <span class="number">0</span>, arr.length - <span class="number">1</span>, temp);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">mergeSort</span><span class="params">(<span class="keyword">int</span>[] arr, <span class="keyword">int</span> left, <span class="keyword">int</span> right, <span class="keyword">int</span>[] temp)</span> </span>{</span><br><span class="line"><span class="keyword">if</span> (left < right) {</span><br><span class="line"><span class="keyword">int</span> mid = (left + right) / <span class="number">2</span>;</span><br><span class="line">mergeSort(arr, left, mid, temp);<span class="comment">// 左边归并排序,使得左子序列有序</span></span><br><span class="line">mergeSort(arr, mid + <span class="number">1</span>, right, temp);<span class="comment">// 右边归并排序,使得右子序列有序</span></span><br><span class="line">merge(arr, left, mid, right, temp);<span class="comment">// 将两个有序子数组合并操作</span></span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">merge</span><span class="params">(<span class="keyword">int</span>[] arr, <span class="keyword">int</span> left, <span class="keyword">int</span> mid, <span class="keyword">int</span> right,</span></span></span><br><span class="line"><span class="function"><span class="params"><span class="keyword">int</span>[] temp)</span> </span>{</span><br><span class="line"><span class="keyword">int</span> i = left;<span class="comment">// 左序列指针</span></span><br><span class="line"><span class="keyword">int</span> j = mid + <span class="number">1</span>;<span class="comment">// 右序列指针</span></span><br><span class="line"><span class="keyword">int</span> t = <span class="number">0</span>;<span class="comment">// 临时数组指针</span></span><br><span class="line"><span class="keyword">while</span> (i <= mid && j <= right) {</span><br><span class="line"><span class="keyword">if</span> (arr[i] <= arr[j]) {</span><br><span class="line">temp[t++] = arr[i++];</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line">temp[t++] = arr[j++];</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"><span class="keyword">while</span> (i <= mid) {<span class="comment">// 将左边剩余元素填充进temp中</span></span><br><span class="line">temp[t++] = arr[i++];</span><br><span class="line">}</span><br><span class="line"><span class="keyword">while</span> (j <= right) {<span class="comment">// 将右序列剩余元素填充进temp中</span></span><br><span class="line">temp[t++] = arr[j++];</span><br><span class="line">}</span><br><span class="line">t = <span class="number">0</span>;</span><br><span class="line"><span class="comment">// 将temp中的元素全部拷贝到原数组中</span></span><br><span class="line"><span class="keyword">while</span> (left <= right) {</span><br><span class="line">arr[left++] = temp[t++];</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 8.基数排序用于大量数,很长的数进行排序时。</span></span><br><span class="line"><span class="comment"> * 平均时间复杂度最坏时间复杂度空间复杂度是否稳定</span></span><br><span class="line"><span class="comment"> * O(N∗M)O(N∗M)O(M)是</span></span><br><span class="line"><span class="comment"> * 将所有的数的个位数取出,按照个位数进行排序,构成一个序列。</span></span><br><span class="line"><span class="comment"> * 将新构成的所有的数的十位数取出,按照十位数进行排序,构成一个序列。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">sort</span><span class="params">(<span class="keyword">int</span>[] number, <span class="keyword">int</span> d)</span> </span>{</span><br><span class="line"><span class="keyword">int</span> k = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">int</span> n = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">int</span> m = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">int</span>[][] temp = <span class="keyword">new</span> <span class="keyword">int</span>[number.length][number.length];</span><br><span class="line"><span class="keyword">int</span>[] order = <span class="keyword">new</span> <span class="keyword">int</span>[number.length];</span><br><span class="line"><span class="keyword">while</span> (m <= d) {</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < number.length; i++) {</span><br><span class="line"><span class="keyword">int</span> lsd = ((number[i] / n) % <span class="number">10</span>);</span><br><span class="line">temp[lsd][order[lsd]] = number[i];</span><br><span class="line">order[lsd]++;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i < d; i++) {</span><br><span class="line"><span class="keyword">if</span> (order[i] != <span class="number">0</span>)</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j < order[i]; j++) {</span><br><span class="line">number[k] = temp[i][j];</span><br><span class="line">k++;</span><br><span class="line">}</span><br><span class="line">order[i] = <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line">n *= <span class="number">10</span>;</span><br><span class="line">k = <span class="number">0</span>;</span><br><span class="line">m++;</span><br><span class="line">}</span><br><span class="line">} </span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>Algorithm<br>
</summary>
<category term="java" scheme="http://www.jmzhang.com/categories/java/"/>
<category term="Algorithm" scheme="http://www.jmzhang.com/categories/java/Algorithm/"/>
<category term="java" scheme="http://www.jmzhang.com/tags/java/"/>
<category term="Algorithm" scheme="http://www.jmzhang.com/tags/Algorithm/"/>
</entry>
<entry>
<title>java关键字volatile</title>
<link href="http://www.jmzhang.com/2018/09/05/java%E5%85%B3%E9%94%AE%E5%AD%97volatile/"/>
<id>http://www.jmzhang.com/2018/09/05/java关键字volatile/</id>
<published>2018-09-04T21:34:53.000Z</published>
<updated>2018-09-05T10:43:56.188Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p>Volatile中文译为【易变的、不稳定的】,它被用来修饰那些被不同的线程访问和修改的变量。</p><p>学习volatile我们首先要来看一下Java内存模型(即Java Memory Model,简称JMM)。<br><a id="more"></a></p><p><img src="http://head.jmzhang.xin/github/su1.png" alt="image"></p><p>Java内存模型中规定了所有的变量都存储在主内存中,每条java线程各自拥有自己的工作内存,线程的工作内存中保存了该线程使用到的主内存中的共享变量的副本,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成,线程、主内存和工作内存的交互关系如上图所示。</p><p>Volatile 修饰的变量即为主内存中的共享变量,当一个共享变量被volatile<br>修饰后,那么当这个变量在工作内存发生了变化后,必须要马上写到主内存中,而线程读取到是volatile修饰的变量时,必须去主内存中去获取最新的值,而不是读工作内存中主内存的副本,这就有效的保证了线程之间变量的可见性。</p><p>这就是volatile的第一个特性,内存可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。</p><p>我们来看一段代码:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">VolatileTest01</span> </span>{</span><br><span class="line"> <span class="comment">// a是一个验证结果的变量 </span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> a=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> b=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">static</span> <span class="keyword">boolean</span> stop=<span class="keyword">false</span>;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException </span>{</span><br><span class="line"></span><br><span class="line"> ThreadA threadA=<span class="keyword">new</span> ThreadA();</span><br><span class="line"> ThreadB threadB=<span class="keyword">new</span> ThreadB();</span><br><span class="line"> threadA.start();</span><br><span class="line"> threadB.start();</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//线程A</span></span><br><span class="line"> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ThreadA</span> <span class="keyword">extends</span> <span class="title">Thread</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">while</span>(!stop) {</span><br><span class="line"> System.out.println(a);</span><br><span class="line"> a++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//线程B</span></span><br><span class="line"> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ThreadB</span> <span class="keyword">extends</span> <span class="title">Thread</span></span>{</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>{</span><br><span class="line"> b=<span class="number">666</span>;</span><br><span class="line"> stop=<span class="keyword">true</span>;</span><br><span class="line"> b=<span class="number">666</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>我们会发现,当线程B执行语句<br><em>stop</em>=<strong>true</strong>;后,会中断线程A的执行。但有没有可能A出现死循环呢?答案是有的,即当线程B更改了stop变量之后还没来得及将stop变量写入主存当中,线程B就转去做其他事了,这时线程A由于不知道线程B对stop变量的更改,因此会一直循环下去,虽然这种情况发生即概论很低,但是一旦发生了将造成很严重的后果。</p><p>使用volatile关键字后我们便可以解决这个问题,但是这样就可以保证线程安全了吗?答案是不能,我们来看一下下面这段代码:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">VolatileTest05</span> </span>{</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">volatile</span> <span class="keyword">static</span> <span class="keyword">int</span> num=<span class="number">0</span>;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i<<span class="number">10</span>;i++){</span><br><span class="line"><span class="keyword">new</span> Thread(</span><br><span class="line"><span class="keyword">new</span> Runnable() {</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>{</span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">Thread.sleep(<span class="number">1</span>);</span><br><span class="line">} <span class="keyword">catch</span> (Exception e) {</span><br><span class="line">e.printStackTrace();</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>;j<<span class="number">100</span>;j++){</span><br><span class="line">num++;</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}).start();</span><br><span class="line">}</span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line">Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">} <span class="keyword">catch</span> (Exception e) {</span><br><span class="line">e.printStackTrace();</span><br><span class="line">}</span><br><span class="line">System.out.println(<span class="string">"num=:"</span>+num);</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>通过上面的代码我们创建10个线程,每个线程中让num自增100次。执行后你会发现结果并不是我们想的1000,而是小于1000.这是为什么呢?因为volatile并不能让一个操作变成原子操作。Num++本身并不是原子操作,转换为字节码是这样的:</p><p>getstatic //读取静态变量(num)</p><p>iconst_1 //定义常量1</p><p>iadd //num增加1</p><p>putstatic //把num结果同步到主内存</p><p>虽然每次get后得到的都是最新变量值,但是进行idd的时候,由于非原子性操作,其他线程可能已经将num++执行了很多次,此时这个线程更新出的num便已经不是我们所期望得到的num值。</p><p>JVM在编译Java代码的时候,或者CPU在执行JVM字节码的时候,为了在不改变程序执行结果的前提下,优化程序的运行效率会对现有的指令顺序进行重新排序。</p><p>Volatile第二个特性即是可以防止指令重排序。</p><p>我们来看下面这个例子:</p><p>boolean contextReady = false;</p><p>在线程A中执行:</p><p>context = loadContext();//初始化context</p><p>contextReady = true;</p><p>在线程B中执行:</p><p>while( ! contextReady ){</p><p>sleep(200);</p><p>}</p><p>doAfterContextReady (context);</p><p>但如果一旦线程A中的指令重排序,会变成这样的执行顺序:</p><p>boolean contextReady = false;</p><p>线程A:</p><p>contextReady = true;</p><p>context = loadContext();//初始化context</p><p>线程B:</p><p>while( ! contextReady ){</p><p>sleep(200);</p><p>}</p><p>doAfterContextReady (context);</p><p> 我们发现context并没有进行初始化线程B跳出循环等待后便执行了doAfterContextReady<br>(context)方法,程序报错。</p><p> 此时我们可以给contextReady 增加volatile方法,以此解决关于contextReady<br>的指令重排序的问题。</p>]]></content>
<summary type="html">
<p>Volatile中文译为【易变的、不稳定的】,它被用来修饰那些被不同的线程访问和修改的变量。</p>
<p>学习volatile我们首先要来看一下Java内存模型(即Java Memory Model,简称JMM)。<br>
</summary>
<category term="java" scheme="http://www.jmzhang.com/categories/java/"/>
<category term="java" scheme="http://www.jmzhang.com/tags/java/"/>
<category term="volatile" scheme="http://www.jmzhang.com/tags/volatile/"/>
</entry>
<entry>
<title>TCP三次握手四次挥手</title>
<link href="http://www.jmzhang.com/2018/09/04/TCP%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E5%92%8C%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B/"/>
<id>http://www.jmzhang.com/2018/09/04/TCP三次握手和四次挥手/</id>
<published>2018-09-03T21:34:53.000Z</published>
<updated>2018-09-04T13:29:26.000Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p>由于网上关于TCP三次握手四次挥手的内容已经很丰富,所以我们今天趣味讲解一下TCP三次握手和四次挥手。<br><a id="more"></a></p><p><strong>三次握手:</strong></p><p>首先先上图:</p><p>![TCP三次握手]<br><img src="http://head.jmzhang.xin/img/TCP%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B.png" alt="image"></p><p>由于我给客户端和服务端都上了色,所以暂且就叫他们小蓝(Client)和小绿(Server)就好了。</p><p>由于一次意外,两人都双目失明,看不见了。他们只能通过声音辨认对方。</p><ol><li><p>小蓝首先叫了一声小绿(syn)</p></li><li><p>小绿听见听见小蓝在叫自己,便答应了一声自己在(ack),但小绿怕小蓝叫的是其他的小绿,便问小蓝是在叫自己吗(syn),小蓝听到后知道了是小绿,便进入(established)状态。</p></li><li><p>最后小蓝也答应了一声是自己(ack),小绿听到后进入(established)状态。</p></li></ol><p>这其中还有两个中间态:syn_sent和syn_rcvd,这两个状态叫【半打开】状态,也就是两人呼唤对方。Syn_sent是客户端的半打开状态,sun_rcvd是服务端的半打开状态。</p><p>Syn_sent : syn package has been sent</p><p>Syn_rcvd : syn package has been received</p><p>官方语言:</p><ol><li><p>TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;</p></li><li><p>TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号<br>seq=x ,此时,TCP客户端进程进入了<br>SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。</p></li><li><p>TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该<br>ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号<br>seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。</p></li><li><p>TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。</p></li><li><p>当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。 </p></li></ol><p><strong>四次挥手:</strong></p><p>![TCP四次挥手]<br><img src="http://head.jmzhang.xin/img/TCP%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B.png" alt="image"></p><p>两人离别的时候,</p><ol><li><p>小蓝说“我要走了”(FIN)</p></li><li><p>小绿回应“那好吧”(ACK)</p></li><li><p>此时小绿说了一些话,但发现小蓝真的不说话了,就说“我也走了”(FIN)</p></li><li><p>小蓝回应了一句“好的”(ACK)</p></li></ol><p>官方语言:</p><ol><li><p>客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。</p></li><li><p>服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。</p></li><li><p>客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。</p></li><li><p>服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。</p></li><li><p>客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。</p></li><li><p>服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。</p></li></ol><p>状态time_wait是一个非常特殊的状态,它是主动关闭的一方在回复完对方后进入的一个长期状态,这个状态标准的持续时间是4分钟,4分钟后才会进入到closed状态,释放套接字资源。不过在具体实现上这个时间是可以调整的。</p><p>这个后果就是持续4分钟的time_wait状态,不能释放套接字资源(端口),就好比守寡期,这段时间内套接字资源(端口)不得回收利用。</p><p>它的作用是重传最后一个ack报文,确保对方可以收到。因为如果对方没有收到ack的话,会重传fin报文,处于time_wait状态的套接字会立即向对方重发ack报文。</p><p>同时在这段时间内,该链接在对话期间于网际路由上产生的残留报文(因为路径过于崎岖,数据报文走的时间太长,重传的报文都收到了,原始报文还在路上)传过来时,都会被立即丢弃掉。4分钟的时间足以使得这些残留报文彻底消逝。不然当新的端口被重复利用时,这些残留报文可能会干扰新的链接。</p><p>4分钟就是2个MSL,每个MSL是2分钟。MSL就是maximium segment<br>lifetime——最长报文寿命。这个时间是由官方RFC协议规定的。至于为什么是2个MSL而不是1个MSL呢?</p><p>第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。</p><p>第二,防止“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。</p><p>最后一个问题,为什么建立连接是三次握手,关闭连接确是四次挥手呢?</p><p>建立连接的时候,<br>服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。</p><p>而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。</p><p>四次挥手也并不总是四次挥手,中间的两个动作有时候是可以合并一起进行的,这个时候就成了三次挥手,主动关闭方就会从fin_wait_1状态直接进入到time_wait状态,跳过了fin_wait_2状态。</p><p><strong>扩展:TCP数据传输</strong></p><p>数据传输过程即是小蓝和小绿对话的过程。</p><p>只不过两人隔着河,且都看不见,所以当一方说话后(data)需要对方听到了回应一声(ACK)。</p><p>如果小蓝喊了一句,半天没听到小绿回复,小蓝就认为自己的话被大风吹走了,小绿没听见,所以需要重新喊话,这就是【tcp重传】。</p><p>也有可能是小绿听到了小蓝的话,但是小绿向小蓝的回复被大风吹走了,以至于小蓝没听见小绿的回复。小蓝并不能判断究竟是自己的话被大风吹走了还是小绿的回复被大风吹走了,小蓝也不用管,重传一下就是。</p><p>既然会重传,小绿就有可能同一句话听见了两次,这就是【去重】。【重传】和【去重】工作操作系统的网络内核模块都已经帮我们处理好了。</p><p>小蓝可以向小绿喊话,同样小绿也可以向小蓝喊话,因为tcp链接是「双工的」,双方都可以主动发起数据传输。不过无论是哪方喊话,都需要收到对方的确认才能认为对方收到了自己的喊话。</p><p>小蓝可能是个八卦,一说连说了八句话,这时候小绿可以不用一句一句回复,而是连续听了这八句话之后,一起向对方回复说前面你说的八句话我都听见了,这就是批量ack。但是小蓝也不能一次性说了太多话,小绿的脑子短时间可能无法消化太多,两人之间需要有协商好的合适的发送和接受速率,这个就是【TCP窗口大小】。</p><p>网络环境的数据交互同人类之间的对话还要复杂一些,它存在数据包乱序的现象。同一个来源发出来的不同数据包在「网际路由」上可能会走过不同的路径,最终达到同一个地方时,顺序就不一样了。操作系统的网络内核模块会负责对数据包进行排序,到用户层时顺序就已经完全一致了。</p><p>好了,今天就介绍到这里了,说的比较简单,深的等以后写,每天进步一点点,希望世界充满正能量!</p>]]></content>
<summary type="html">
<p>由于网上关于TCP三次握手四次挥手的内容已经很丰富,所以我们今天趣味讲解一下TCP三次握手和四次挥手。<br>
</summary>
<category term="TCP" scheme="http://www.jmzhang.com/categories/TCP/"/>
<category term="TCP" scheme="http://www.jmzhang.com/tags/TCP/"/>
<category term="网络" scheme="http://www.jmzhang.com/tags/%E7%BD%91%E7%BB%9C/"/>
</entry>
<entry>
<title>hexo+github搭建个人博客</title>
<link href="http://www.jmzhang.com/2018/09/03/hexo+github%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/"/>
<id>http://www.jmzhang.com/2018/09/03/hexo+github搭建个人博客/</id>
<published>2018-09-02T21:34:53.000Z</published>
<updated>2018-09-10T15:01:23.243Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><h1 id="博主我用过很多云服务器、云主机搭建个人博客网站,但没用过github的page页,想尝试下,搞了一会就搭建完成了,总的来说很顺利,在这里分享给大家。"><a href="#博主我用过很多云服务器、云主机搭建个人博客网站,但没用过github的page页,想尝试下,搞了一会就搭建完成了,总的来说很顺利,在这里分享给大家。" class="headerlink" title="博主我用过很多云服务器、云主机搭建个人博客网站,但没用过github的page页,想尝试下,搞了一会就搭建完成了,总的来说很顺利,在这里分享给大家。"></a>博主我用过很多云服务器、云主机搭建个人博客网站,但没用过github的page页,想尝试下,搞了一会就搭建完成了,总的来说很顺利,在这里分享给大家。</h1><a id="more"></a><h1 id="安装Hexo"><a href="#安装Hexo" class="headerlink" title="安装Hexo"></a>安装Hexo</h1><h2 id="安装node-js"><a href="#安装node-js" class="headerlink" title="安装node.js"></a>安装node.js</h2><ul><li><p><a href="https://nodejs.org/en/" target="_blank" rel="noopener">node.js官方下载地址</a></p></li><li><p>从上面的链接下载node.js,并安装。 </p></li><li><p>下载LTS那个即可</p></li></ul><h2 id="申请Github账号"><a href="#申请Github账号" class="headerlink" title="申请Github账号"></a>申请Github账号</h2><ul><li><p><a href="https://github.com/join?source=header-home" target="_blank" rel="noopener">Github注册页面</a></p></li><li><p>输入<strong>用户名,Email,密码</strong>,注册账号。比如我的用户名是:JasonZhangCauc</p></li></ul><h3 id="创建博客仓库"><a href="#创建博客仓库" class="headerlink" title="创建博客仓库"></a>创建博客仓库</h3><ul><li>注意,仓库名应该为:用户名.github.io。比如,我的仓库名是:<a href="https://github.com/xuezhisd/xuezhisd.github.io" target="_blank" rel="noopener">JasonZhangCauc.github.io</a>。</li></ul><h2 id="安装git"><a href="#安装git" class="headerlink" title="安装git"></a>安装git</h2><ul><li><p><a href="https://git-scm.com/downloads/" target="_blank" rel="noopener">git下载地址</a></p></li><li><p>下载git安装文件,双击执行安装。</p></li></ul><h3 id="配置ssh"><a href="#配置ssh" class="headerlink" title="配置ssh"></a>配置ssh</h3><ul><li><p>打开git bash终端。</p></li><li><p>设置user.name和user.email。</p></li></ul><p>git config –global user.name “你的GitHub用户名”</p><p>git config –global user.email “你的GitHub注册邮箱”</p><ul><li>生成ssh密匙</li></ul><p>ssh-keygen -t rsa -C “你的GitHub注册邮箱”</p><ul><li>此时,在用户文件夹下就会有一个新的文件夹.ssh,里面有刚刚创建的ssh密钥文件id_rsa和id_rsa.pub。</li></ul><h3 id="将公匙添加到github上"><a href="#将公匙添加到github上" class="headerlink" title="将公匙添加到github上"></a>将公匙添加到github上</h3><ul><li><p>详细教程自行baidu。</p></li><li><p>用户头像→Settings→SSH and GPG keys→New SSH<br>key→将id_rsa.pub中的内容复制到Key文本框中,然后点击Add SSH<br>key(添加SSH)按钮。</p></li></ul><h2 id="安装hexo"><a href="#安装hexo" class="headerlink" title="安装hexo"></a>安装hexo</h2><ul><li>执行以下命令安装hexo。</li></ul><p># 安装hexo</p><p>npm install hexo-cli g# 初始化博客文件夹</p><p>hexo init blog# 切换到该路径cd blog# 安装hexo的扩展插件</p><p>npm install# 安装其它插件</p><p>npm install hexo-server –save</p><p>npm install hexo-admin –save</p><p>npm install hexo-generator-archive –save</p><p>npm install hexo-generator-feed –save</p><p>npm install hexo-generator-search –save</p><p>npm install hexo-generator-tag –save</p><p>npm install hexo-deployer-git –save</p><p>npm install hexo-generator-sitemap –save</p><h2 id="初探hexo"><a href="#初探hexo" class="headerlink" title="初探hexo"></a>初探hexo</h2><ul><li>第一次使用hexo,在本地创建服务器使用。</li></ul><p># 生成静态页面</p><p>hexo generate# 开启本地服务器</p><p>hexo s</p><ul><li><p>打开浏览器,地址栏中输入:<a href="http://localhost:4000/" target="_blank" rel="noopener">http://localhost:4000/</a>,应该可以看见刚刚创建的博客了。</p></li><li><p>问题:为什么访问<a href="http://localhost:4000/" target="_blank" rel="noopener">http://localhost:4000/</a>,无反应? </p><ul><li>解决方法:可能是由于端口问题引起的。使用Ctrl+C中断本地服务,使用命令hexo<br>s -p<br>5000重新开启本地服务,访问<a href="http://localhost:5000/" target="_blank" rel="noopener">http://localhost:5000/</a>可以看到博客页面了。</li></ul></li></ul><h2 id="将hexo博客部署到github上"><a href="#将hexo博客部署到github上" class="headerlink" title="将hexo博客部署到github上"></a>将hexo博客部署到github上</h2><ul><li>修改配置文件<strong>blog/_config.yml</strong>,修改deploy项的内容,如下所示:</li></ul><p># Deployment 注释## Docs: <a href="https://hexo.io/docs/deployment.htmldeploy" target="_blank" rel="noopener">https://hexo.io/docs/deployment.htmldeploy</a>:</p><p># 类型</p><p>type: git</p><p># 仓库</p><p>repo: git\@github.com:JasonZhangCauc/JasonZhangCauc.github.io.git</p><p># 分支</p><p>branch: master</p><ul><li><p>注意:<strong>type: git</strong>中的冒号后面由空格。</p></li><li><p>注意:将git\@github.com:<strong>JasonZhangCauc/JasonZhangCauc</strong>.github.io.git中的用户名换成自己的用户名git\@github.com:<strong>github_username/github_username</strong>.github.io.git。</p></li></ul><h3 id="部署hexo"><a href="#部署hexo" class="headerlink" title="部署hexo"></a>部署hexo</h3><ul><li>输入下面的命令将hexo博客部署到github中:</li></ul><p># 清空静态页面</p><p>hexo clean# 生成静态页面</p><p>hexo generate# 部署</p><p>hexo deploy</p><ul><li>打开网页,输入<a href="http://github_username.github.io/" target="_blank" rel="noopener">http://github_username.github.io</a>,打开github上托管的博客。如我的博客地址是:<a href="http://xuezhisd.github.io/" target="_blank" rel="noopener">http://JasonZhangCauc.github.io</a>。</li></ul><h1 id="hexo命令缩写"><a href="#hexo命令缩写" class="headerlink" title="hexo命令缩写"></a>hexo命令缩写</h1><ul><li>hexo支持命令缩写,如下所示。hexo g等价于hexo generate。</li></ul><p>hexo g:hexo generate</p><p>hexo c:hexo clean</p><p>hexo s:hexo server</p><p>hexo d:hexo deploy</p><h1 id="hexo组合命令"><a href="#hexo组合命令" class="headerlink" title="hexo组合命令"></a>hexo组合命令</h1><p># 清除、生成、启动</p><p>hexo clean && hexo g -s# 清除、生成、部署</p><p>hexo clean && hexo g -d</p><h1 id="附博客维护方法:"><a href="#附博客维护方法:" class="headerlink" title="附博客维护方法:"></a>附博客维护方法:</h1><p><a href="http://theme-next.iissnan.com/getting-started.html" target="_blank" rel="noopener">http://theme-next.iissnan.com/getting-started.html</a></p>]]></content>
<summary type="html">
<h1 id="博主我用过很多云服务器、云主机搭建个人博客网站,但没用过github的page页,想尝试下,搞了一会就搭建完成了,总的来说很顺利,在这里分享给大家。"><a href="#博主我用过很多云服务器、云主机搭建个人博客网站,但没用过github的page页,想尝试下,搞了一会就搭建完成了,总的来说很顺利,在这里分享给大家。" class="headerlink" title="博主我用过很多云服务器、云主机搭建个人博客网站,但没用过github的page页,想尝试下,搞了一会就搭建完成了,总的来说很顺利,在这里分享给大家。"></a>博主我用过很多云服务器、云主机搭建个人博客网站,但没用过github的page页,想尝试下,搞了一会就搭建完成了,总的来说很顺利,在这里分享给大家。</h1>
</summary>
<category term="hexo" scheme="http://www.jmzhang.com/categories/hexo/"/>
<category term="hexo" scheme="http://www.jmzhang.com/tags/hexo/"/>
<category term="github" scheme="http://www.jmzhang.com/tags/github/"/>
</entry>
<entry>
<title>Hello World</title>
<link href="http://www.jmzhang.com/2018/09/02/hello-world/"/>
<id>http://www.jmzhang.com/2018/09/02/hello-world/</id>
<published>2018-09-02T12:03:22.593Z</published>
<updated>2018-09-23T03:43:09.254Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><p>Hello! Friends!<br><a id="more"></a></p><ul><li><i class="fa fa-pencil"></i> 铅笔</li><li><i class="fa fa-cloud-upload"></i> 上传</li><li><i class="fa fa-download"></i> 下载</li><li><i class="fa fa-download fa-2x"></i> 下载两倍大</li></ul><figure class="highlight"><figcaption><span>java</span><a href="https://jasonzhangcauc.github.io/" target="_blank" rel="noopener">源站</a></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><head></span><br><span class="line"> <link rel=<span class="string">"stylesheet"</span> type=<span class="string">"text/css"</span> href=<span class="string">"http://github.jmzhang.top/css/EnlighterJS.min.css"</span> /></span><br><span class="line"> <script type="text/javascript" src="http://github.jmzhang.top/js/MooTools.min.js"></script></span><br><span class="line"> <script type="text/javascript" src="http://github.jmzhang.top/js/EnlighterJS.min.js" ></script></span><br><span class="line"> <meta name=<span class="string">"EnlighterJS"</span> content=<span class="string">"Advanced javascript based syntax highlighting"</span> data-indent=<span class="string">"4"</span> data-selector-block=<span class="string">"pre"</span> data-selector-inline=<span class="string">"code.special"</span> /></span><br><span class="line"></head></span><br><span class="line"><body></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">duiliecz</span> </span>{ <span class="comment">// 队列操作类</span></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> args</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">int</span> i = <span class="number">0</span>; <span class="comment">// 队列长</span></span><br><span class="line"> <span class="keyword">private</span> duilie top = <span class="keyword">new</span> duilie(<span class="string">""</span>); <span class="comment">// 队列头</span></span><br><span class="line"> <span class="keyword">private</span> duilie end = <span class="keyword">new</span> duilie(<span class="string">""</span>); <span class="comment">// 队列尾</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(String s)</span> </span>{ <span class="comment">// 添加队列</span></span><br><span class="line"> duilie m = <span class="keyword">new</span> duilie(s);</span><br><span class="line"> <span class="keyword">if</span> (i != <span class="number">0</span>) {</span><br><span class="line"> m.setS(top.getS());</span><br><span class="line"> top.setS(m);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> top.setS(m);</span><br><span class="line"> end.setS(m);</span><br><span class="line"> }</span><br><span class="line"> i++;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></body></span><br></pre></td></tr></table></figure><blockquote class="blockquote-center"><p>居中<br>人生乃是一面镜子,<br>从镜子里认识自己,<br>我要称之为头等大事,<br>也只是我们追求的目的!</p></blockquote><div class="note default"><p>default</p></div><div class="note primary"><p>primary</p></div><div class="note success"><p>success</p></div><div class="note info"><p>info</p></div><div class="note warning"><p>warning</p></div><div class="note danger"><p>danger</p></div><div class="note danger no-icon"><p>danger no-icon</p></div><span class="label default">default</span><span class="label primary">primary</span><span class="label success">success</span><span class="label info">info</span><span class="label warning">warning</span><span class="label danger">danger</span><div class="tabs" id="选项卡"><ul class="nav-tabs"><li class="tab"><a href="#选项卡-1">选项卡 1</a></li><li class="tab active"><a href="#选项卡-2">选项卡 2</a></li><li class="tab"><a href="#选项卡-3">选项卡 3</a></li></ul><div class="tab-content"><div class="tab-pane" id="选项卡-1"><p><strong>这是选项卡 1</strong> 呵呵哈哈哈哈哈哈哈哈……</p></div><div class="tab-pane active" id="选项卡-2"><p><strong>这是选项卡 2</strong> ei</p></div><div class="tab-pane" id="选项卡-3"><p><strong>这是选项卡 3</strong> 哇,你找到我了!φ(≧ω≦*)♪~</p></div></div></div><div class="tabs" id="fifth-unique-name"><ul class="nav-tabs"><li class="tab active"><a href="#fifth-unique-name-1"><i class="fa fa-text-width" style="text-align: center;"></i></a></li><li class="tab"><a href="#fifth-unique-name-2"><i class="fa fa-amazon" style="text-align: center;"></i></a></li><li class="tab"><a href="#fifth-unique-name-3"><i class="fa fa-bold" style="text-align: center;"></i></a></li></ul><div class="tab-content"><div class="tab-pane active" id="fifth-unique-name-1"><p><strong>This is Tab 1.</strong></p></div><div class="tab-pane" id="fifth-unique-name-2"><p><strong>This is Tab 2.</strong></p></div><div class="tab-pane" id="fifth-unique-name-3"><p><strong>This is Tab 3.</strong></p></div></div></div><div class="tabs" id="sixth-unique-name"><ul class="nav-tabs"><li class="tab active"><a href="#sixth-unique-name-1"><i class="fa fa-text-width" "=""></i>Solution 1</a></li><li class="tab"><a href="#sixth-unique-name-2"><i class="fa fa-amazon" "=""></i>Solution 2</a></li><li class="tab"><a href="#sixth-unique-name-3"><i class="fa fa-bold" "=""></i>Solution 3</a></li></ul><div class="tab-content"><div class="tab-pane active" id="sixth-unique-name-1"><p><strong>This is Tab 1.</strong></p></div><div class="tab-pane" id="sixth-unique-name-2"><p><strong>This is Tab 2.</strong></p></div><div class="tab-pane" id="sixth-unique-name-3"><p><strong>This is Tab 3.</strong></p></div></div></div><blockquote class="jasonblue">内容class=”jasonblue”</blockquote><br><blockquote class="jasongreen">内容class=”jasongreen”</blockquote><br><blockquote class="jasonred">内容class=”jasonred”</blockquote><br><blockquote class="jasonyellow">内容class=”jasonyellow”</blockquote><p><span id="jasonnumber">1.</span><span id="jasonnumber">2.</span><br><span id="jasonnumber">3.</span></p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html" target="_blank" rel="noopener">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html" target="_blank" rel="noopener">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/deployment.html" target="_blank" rel="noopener">Deployment</a></p><p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.</p>]]></content>
<summary type="html">
<p>Hello! Friends!<br>
</summary>
</entry>
</feed>