-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
606 lines (289 loc) · 220 KB
/
search.xml
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>一起学Linux之 shell脚本的服务封装</title>
<link href="/3194397260.html"/>
<url>/3194397260.html</url>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在使用springboot的过程中由于大多数使用的是springboot自带的tomcat,所以启动方式为 java -jar xxx.jar 但是这样启动不好维护,故而需要写一个脚本来维护。</p><a id="more"></a><h3 id="启动脚本"><a href="#启动脚本" class="headerlink" title="启动脚本"></a>启动脚本</h3><p>废话不多bb,直接上脚本,内容如下:</p><figure class="highlight shell hljs"><figcaption><span>[] [tomcat.sh]</span></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><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-meta">#</span><span class="hljs-bash">! /bin/bash</span></span><br><span class="line"><span class="hljs-meta">#</span><span class="hljs-bash"> jar包位置</span></span><br><span class="line">APP_NAME=/xxx/xx/xxx.jar</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">#</span><span class="hljs-bash">使用说明,用来提示输入参数</span></span><br><span class="line">usage() {</span><br><span class="line"> echo "Usage: sh 执行脚本.sh [start|stop|restart|status]"</span><br><span class="line"> exit 1</span><br><span class="line">}</span><br><span class="line"><span class="hljs-meta">#</span><span class="hljs-bash">检查程序是否在运行</span></span><br><span class="line">is_exist(){</span><br><span class="line"> pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `</span><br><span class="line"><span class="hljs-meta"> #</span><span class="hljs-bash">如果不存在返回1,存在返回0 </span></span><br><span class="line"> if [ -z "${pid}" ]; then</span><br><span class="line"> return 1</span><br><span class="line"> else</span><br><span class="line"> return 0</span><br><span class="line"> fi</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">#</span><span class="hljs-bash">启动方法</span></span><br><span class="line">start(){</span><br><span class="line"> is_exist</span><br><span class="line"> if [ $? -eq "0" ]; then</span><br><span class="line"> echo "${APP_NAME} is already running. pid=${pid} ."</span><br><span class="line"> else</span><br><span class="line"> nohup /usr/local/jdk1.8/bin/java -jar $APP_NAME | /usr/local/sbin/cronolog ./logs/catalina-%Y-%m-%d.out 2>&1 & </span><br><span class="line"> fi</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">#</span><span class="hljs-bash">停止方法</span></span><br><span class="line">stop(){</span><br><span class="line"> is_exist</span><br><span class="line"> if [ $? -eq "0" ]; then</span><br><span class="line"> kill -9 $pid</span><br><span class="line"> else</span><br><span class="line"> echo "${APP_NAME} is not running"</span><br><span class="line"> fi </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">#</span><span class="hljs-bash">输出运行状态</span></span><br><span class="line">status(){</span><br><span class="line"> is_exist</span><br><span class="line"> if [ $? -eq "0" ]; then</span><br><span class="line"> echo "${APP_NAME} is running. Pid is ${pid}"</span><br><span class="line"> else</span><br><span class="line"> echo "${APP_NAME} is NOT running."</span><br><span class="line"> fi</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">#</span><span class="hljs-bash">重启</span></span><br><span class="line">restart(){</span><br><span class="line"> stop</span><br><span class="line"> start</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="hljs-meta">#</span><span class="hljs-bash">根据输入参数,选择执行对应方法,不输入则执行使用说明</span></span><br><span class="line">case "$1" in</span><br><span class="line"> "start")</span><br><span class="line"> start</span><br><span class="line"> ;;</span><br><span class="line"> "stop")</span><br><span class="line"> stop</span><br><span class="line"> ;;</span><br><span class="line"> "status")</span><br><span class="line"> status</span><br><span class="line"> ;;</span><br><span class="line"> "restart")</span><br><span class="line"> restart</span><br><span class="line"> ;;</span><br><span class="line"> *)</span><br><span class="line"> usage</span><br><span class="line"> ;;</span><br><span class="line">esac</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>其中cronolog 是一个log切割工具 防止log文件过大的问题。</p><h3 id="封装成服务"><a href="#封装成服务" class="headerlink" title="封装成服务"></a>封装成服务</h3><p>经过上述操作,我们的shell脚本就写好了,写完只需要像执行tomcat中的脚本一样执行这个脚本就可以了。但是这个脚本还有一个问题,那就是运行一次就很棒,但是服务器重启,我们就要手动运行一次,所以我们要开机自启。如何开机自启呢,就需要一个系统服务了。如何封装系统服务呢 ok 请看如下操作:</p><ol><li>进入 centos7 中的/usr/lib/systemd/system 文件夹</li><li>新建xxx.service文件,文件内容如下</li></ol><figure class="highlight plain hljs"><figcaption><span>[] [xxx.service]</span></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></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line">Description=描述</span><br><span class="line">#这个不用变,是启动顺序</span><br><span class="line">After=syslog.target network.target remote-fs.target nss-lookup.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=forking</span><br><span class="line">WorkingDirectory=/xxx/xx</span><br><span class="line">ExecStart=/xxx/xx/bin/service.sh start</span><br><span class="line">ExecReload=/xxx/xx/bin/service.sh restart</span><br><span class="line">ExecStop=/xxx/xx/bin/service.sh stop</span><br><span class="line">PrivateTmp=true</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br></pre></td></tr></table></figure><p>经过上述步骤 我们就新建了一个叫xxx.service 的系统服务,就可以用 services xxx start 启动了,现在只需要把他加入到开机自启里面就可以了,只需要systemctl enable xxx来开启开机自启就可以了,以上就是关于本篇文章的全部内容,另外本文主要描述如何对shell脚本进行服务封装,并非仅仅针对springboot。希望需要帮助到大家</p>]]></content>
<tags>
<tag> Linux </tag>
</tags>
</entry>
<entry>
<title>一起来学maven之nexus私服的搭建</title>
<link href="/1297375589.html"/>
<url>/1297375589.html</url>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>本文假定你知道什么是<code>maven</code>,这里不做过多的阐述,如果有兴趣的话可以尝试看一下<code>maven实战</code>这本书,由于<code>maven</code>的国外仓库贼慢,加上有些自己封装的工具包不能直接放到中央仓库上,所以就有了搭建<code>maven</code>私服的需求,那么我们如何搭建呢?<a id="more"></a>下面我们一起了解一下。</p><h3 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h3><ol><li><code>nexus</code>,我们使用<code>nexus</code>,版本为<code>2.14.17</code>,我们不使用<code>nexus3.x</code>原因是因为<code>nexus3.x</code>如何同步主仓库的索引,如果有知晓的大大,可以评论区告知一下,不胜感激。<a href="https://sonatype-download.global.ssl.fastly.net/repository/downloads-prod-group/oss/nexus-2.14.17-01-bundle.tar.gz" target="_blank" rel="noopener">点我下载nexus</a></li><li><code>jdk1.8</code>,这个没得选,建议<code>jdk1.8</code></li><li>系统要求看公司的要求一般公司建议<code>8核16g</code>。注意:<ul><li>请不要使用root用户允许<code>nexus</code>,所以需要<code>新建</code>一个<code>用户nexus</code></li><li><code>nexus</code>用户打开的文件描述符的数量限制增加到65,536或更高,centos用户可以通过编辑<code>/etc/security/limits.conf</code>文件来增加限制,在该文件中新增<code>nexus - nofile 65536- nofile 65536</code></li></ul></li><li>离线索引文件、离线索引配置文件、解压离线索引的jar,离线索引文件、离线索引配置文件以及可以通过<code>https://repo.maven.apache.org/maven2/.index/</code>这个地址来找到。<code>解压离线索引的jar</code>文件可以在<code>https://search.maven.org/</code>这个搜索仓库中搜索<code>org.apache.maven.indexer:indexer-cli:5.1.1</code>然后点击右上角的下载按钮即可</li></ol><table><thead><tr><th>文件</th><th>说明</th></tr></thead><tbody><tr><td><a href="https://repo.maven.apache.org/maven2/.index/nexus-maven-repository-index.gz" target="_blank" rel="noopener">nexus-maven-repository-index.gz</a></td><td>离线索引文件</td></tr><tr><td><a href="https://repo.maven.apache.org/maven2/.index/nexus-maven-repository-index.properties" target="_blank" rel="noopener">nexus-maven-repository-index.properties</a></td><td>索引配置文件</td></tr></tbody></table><h3 id="安装以及启动"><a href="#安装以及启动" class="headerlink" title="安装以及启动"></a>安装以及启动</h3><ol><li>将下载好的文件找一个合适的地方解压,然后会出现俩目录,<code>nexus-2.14.17-01</code>、<code>sonatype-work</code>一个是服务文件夹,一个是存放数据的文件夹</li><li>将下载好的离线索引文件、离线索引配置文件、解压离线索引的jar这三个放到同一目录下,然后用命令 <code>java -jar indexer-cli-5.1.0.jar -u nexus-maven-repository-index.gz -d indexer</code> 大概4-5分钟的样子就解压完成了。解压好的文件在同级目录下的<code>indexer</code>文件夹下</li><li>将<code>indexer</code>文件夹下的文件复制到<code>${nexus_home}/sonatype-work/nexus/indexer/central-ctx</code>文件夹下</li><li>进入<code>${nexus_home}/nexus-2.14.17-01/bin</code>文件夹下,运行<code>nexus start</code> 就可以启动了</li><li>防火墙放开8081端口就可以通过内网访问了,如果端口不爽可以通过修改<code>${nexus_home}/nexus-2.14.17-01/conf/nexus.properties</code>文件中的<code>application-port</code>属性来修改端口</li><li>记得开机自启、nexus服务的封装。</li></ol><h3 id="迁移"><a href="#迁移" class="headerlink" title="迁移"></a>迁移</h3><p>只需要将<code>nexus-2.14.17-01</code>、<code>sonatype-work</code>俩文件夹打包复制,拷贝到新机器上,然后重启即可</p>]]></content>
<tags>
<tag> nexus </tag>
</tags>
</entry>
<entry>
<title>一起来玩Jenkins之Jenkins的搭建以及项目的构建</title>
<link href="/2074530126.html"/>
<url>/2074530126.html</url>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>在开发完成后,我们都是要将开发好的项目部署到服务器上的,而部署到服务器上的步骤常常是不变的,所以自动化部署是可以实现的,那么如何自动化部署呢?<a id="more"></a> <code>Jenkins</code>可以解决我们这个问题。下面让我们一起来了解一下。</p><h3 id="什么是Jenkins"><a href="#什么是Jenkins" class="headerlink" title="什么是Jenkins"></a>什么是Jenkins</h3><p>Jenkins是开源CI&CD软件领导者, 提供超过1000个插件来支持构建、部署、自动化, 满足任何项目的需要。</p><p>Jenkins功能包括:</p><ol><li>持续的软件版本发布/测试项目。</li><li>监控外部调用执行的工作。</li></ol><h3 id="如何搭建简单的Jenkins环境"><a href="#如何搭建简单的Jenkins环境" class="headerlink" title="如何搭建简单的Jenkins环境"></a>如何搭建简单的Jenkins环境</h3><ol><li>需要准备 <a href="https://jenkins.io/download/" target="_blank" rel="noopener">Jenkins安装包</a>、<code>jdk1.8</code>、<code>tomcat</code></li><li>准备好以后,将Jenkins安装包放入tomcat中的webapps中启动tomcat即可</li><li>浏览器访问端口根据提示找到<code>密码文件</code>,并输入<code>密码文件</code>中的密码以后我们就可以进入到Jenkins的主页面了</li><li>如果不想汉化的,请忽略此步骤。<ul><li>点击左侧的<code>Manage Jenkins</code>。</li><li>点击<code>Manage Plugins</code></li><li>点击<code>第二个选项卡(可选插件)</code>,搜索<code>local</code>找到<code>Localization: Chinese (Simplified)</code>插件安装,并重启<code>Jenkins</code>,这样我们就汉化完成了</li></ul></li></ol><h3 id="如何使用Jenkins"><a href="#如何使用Jenkins" class="headerlink" title="如何使用Jenkins"></a>如何使用Jenkins</h3><p>我们搭建好简单的环境后就一起来了解一下如何使用,下面我们将通过构建<code>git</code>上存储的<code>maven</code>项目来实际操作一下。</p><h4 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作:"></a>准备工作:</h4><ol><li>在Jenkins服务器上搭建好<code>git</code>环境用来拉取<code>git</code>上的代码。准备好<code>maven</code>环境来对项目进行编译。</li><li>Jenkins所需插件的安装 <code>Git Parameter Plug-In</code>、<code>Git plugin</code>、<code>SSH plugin</code>、<code>Publish Over SSH</code>、<code>Maven Integration plugin</code></li><li>注意:安装过程中可能会出现timeout的异常,原因是因为国外的插件库不稳定造成的需要更换地址,更换方式为:<br> <code>Manage Jenkins</code>—><code>Manage Plugins</code>—><code>高级</code>—><code>最底部</code>—><code>修改升级站点</code>。可以修改为的站点有:</li></ol><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">http://mirror.xmission.com/jenkins/updates/update-center.json</span><br><span class="line"></span><br><span class="line">http://mirror.esuni.jp/jenkins/updates/update-center.json</span><br><span class="line"></span><br><span class="line">https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</span><br></pre></td></tr></table></figure><p>一个一个试试,总有一个适合你。笔者用的是第三个,清华大学的镜像</p><ol start="4"><li>Jenkins所在服务器生成私钥,部署服务器上存储公钥,用于<code>Jenkins</code>的远程免密拷贝文件。具体步骤如下<ul><li><code>Jenkins</code>服务器使用命令<code>ssh-keygen -t rsa</code> 然后回车三下,生成私钥,这条命令会在<code>~</code>目录下生成一个.ssh的文件夹。里面文件的含义分别是:<ul><li>id_rsa: 生成的私钥文件</li><li>id_rsa.pub: 生成的公钥文件</li><li>know_hosts: 已知的主机公钥清单</li></ul></li><li>通过<code>sh-copy-id</code>将公钥写入远程服务器中具体命令为:<code>ssh-copy-id [email protected]</code></li></ul></li></ol><h4 id="Jenkins系统配置"><a href="#Jenkins系统配置" class="headerlink" title="Jenkins系统配置"></a>Jenkins系统配置</h4><p>依次点击 <code>Manage Jenkins</code>—><code>Configure System</code> 找到<code>Publish over SSH</code></p><ol><li><p>在<code>Key</code>字段中写写入<code>Jenkins</code>部署服务器中生成好的私钥<br><img src="/images/add_private_key.png" alt></p></li><li><p>新增ssh 服务器,这个可以新增多个,其中<code>Remote Directory</code>字段表示以后拷贝到远程服务器上面的根文件夹是什么。<br><img src="/images/add_ssh_server.png" alt></p></li></ol><h4 id="Jenkins全局配置"><a href="#Jenkins全局配置" class="headerlink" title="Jenkins全局配置"></a>Jenkins全局配置</h4><p>依次点击 <code>Manage Jenkins</code>—><code>Global Tool Configuration</code></p><ol><li><p>新增jdk<br><img src="/images/add_jdk.png" alt></p></li><li><p>新增git<br><img src="/images/add_git.png" alt></p></li><li><p>新增maven<br><img src="/images/add_maven.png" alt></p></li></ol><h4 id="新建任务"><a href="#新建任务" class="headerlink" title="新建任务"></a>新建任务</h4><ol><li><p>点击左侧的<code>新建Item</code>进入如图页面,输入名称,选择构建一个maven项目,也可以复制一个之前已经配置好的项目。进入如图<br><img src="/images/new_item_general.png" alt></p></li><li><p>选择的是<code>Discard old builds(丢弃旧的构建,也可不选)</code>,如图<br><img src="/images/new_item_general_Discard_old_builds.png" alt></p></li><li><p>选择<code>This project is parameterized</code>—>添加参数—><code>Git Parameter</code> 填入如图数据,描述随便写,名称最好见名知意,因为下面会用到<br><img src="/images/git_parameter_setting.png" alt></p></li><li><p>源码管理选择git,<code>Repository URL</code>输入你的项目的git地址(http形式的),点击添加,选择<code>Jenkins</code><br><img src="/images/yuanmaguanli_git.png" alt></p></li><li><p>添加git凭据,用户名输入git账户,密码输入git密码,id可以不写,描述随便写<br><img src="/images/add_pingju.png" alt></p></li><li><p>指定分支输入<code>$</code>加上<code>Git Parameter</code>中的名称,例如我的名称是<code>breach</code>那么这里就写<code>$breach</code><br><img src="/images/git_zhidingfenzhi.png" alt></p></li><li><p>建立环境中在目标和选择里面写入maven命令,注意不需要加mvn,发布步骤选择仅在构建成功时运行<br><img src="/images/yuxianbuzhou.png" alt></p></li><li><p>构建后操作,如图其中<code>Source files</code>表示构建完成后目标文件夹<code>Remove prefix</code>拷贝时不需要拷贝的文件夹<code>Remote directory</code>表示移动的目录,和全局配置中的组合一起,即为最终目录<code>Exec command</code>表示要执行的命令。<br><img src="/images/goujianhoucaozuo.png" alt><br>其中脚本为</p></li></ol><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">#!/bin/bash</span><br><span class="line">#定义一些常用变量</span><br><span class="line">log_time=`date +%Y-%m-%d_%H:%M:%S`</span><br><span class="line">tomcat_home=/opt/tomcat80</span><br><span class="line">web_backup_home=/root/webbak/lbrz-admin-$log_time</span><br><span class="line">war_base_home=/opt/hachi-lbrz</span><br><span class="line">#停止服务,并备份文件</span><br><span class="line">echo "********************************** 开始停止服务并备份文件`date +%Y-%m-%d_%H:%M:%S`*************************************"</span><br><span class="line">/opt/tomcat80/bin/shutdown.sh</span><br><span class="line">mkdir -p $web_backup_home</span><br><span class="line">mv $tomcat_home/webapps/ROOT* $web_backup_home</span><br><span class="line">echo "************************备份完成`date +%Y-%m-%d_%H:%M:%S` **********************************"</span><br><span class="line">echo "************************准备启动服务`date +%Y-%m-%d_%H:%M:%S` **********************************"</span><br><span class="line">mv $war_base_home/web-admin.war $tomcat_home/webapps/ROOT.war</span><br><span class="line">/opt/tomcat80/bin/startup.sh</span><br><span class="line">echo "************************服务启动完成`date +%Y-%m-%d_%H:%M:%S` **********************************"</span><br></pre></td></tr></table></figure><p>通过上述步骤我们就可以通过<code>Jenkins</code>进行多分支打包,并部署到服务器上了。</p>]]></content>
<tags>
<tag> Jenkins </tag>
</tags>
</entry>
<entry>
<title>基于SpringBoot2.x,Quartz的定时任务的动态修改</title>
<link href="/2628687485.html"/>
<url>/2628687485.html</url>
<content type="html"><![CDATA[<h1 id="概述"><a href="#概述" class="headerlink" title="概述:"></a>概述:</h1><p>在开发中有的时候需要去手动禁止和启用定时任务,修改定时任务的<code>cron</code>表达式然后再让其动态生效于是有了这个例子 本例子根据 zhuyanpeng的demo 改编有兴趣的童鞋可以github搜索zhuyanpeng看他的demo.本人将其中<code>Springboot1.x</code>升级为<code>2.x</code> 删除原有的<code>SpringUtil.java</code> 由<code>Spring</code>管理<code>TaskUtils.java</code> 另,多谢<code>@zhuyanpeng</code> 提供思路.代码稍后放出. 如有启发,请点<code>star</code></p><a id="more"></a><h1 id="相关技术"><a href="#相关技术" class="headerlink" title="相关技术"></a>相关技术</h1><p>本次用到的技术主要有 <code>springboot2.x</code> <code>Jpa</code> <code>Quartz</code> <code>H2</code> <code>Thymeleaf</code> </p><h1 id="具体流程"><a href="#具体流程" class="headerlink" title="具体流程"></a>具体流程</h1><p>1) 修改 <code>Quartz</code> 注入方式为<code>Spring</code>的 防止在执行<code>Job</code>的时候自动注入为<code>Null</code>,因为 在<code>Quartz</code>框架中,<code>Job</code> 是通过反射出来的实例,不受<code>Spring</code>的管理。具体方式为重写<code>SpringBeanJobFactory</code>类中的<code>createJobInstance</code>方法,将创建的<code>Job</code>实例添加到<code>applicationContext</code>中,交给<code>Spring</code>管理。具体代码详见 <code>HachiQuartzJobFactory.java</code></p><figure class="highlight java hljs"><figcaption><span>[] [HachiQuartzJobFactory.java]</span></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><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">import</span> org.quartz.spi.TriggerFiredBundle;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.beans.factory.config.AutowireCapableBeanFactory;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.scheduling.quartz.AdaptableJobFactory;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@BelongsProject</span>: spring-boot-dynamic-quartz</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@BelongsPackage</span>: com.hachismart.config</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@Author</span>: smallodd</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@CreateTime</span>: 2019-04-15 16:48</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span>: 修改QuartzJob 的注入方式为spring的</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HachiQuartzJobFactory</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AdaptableJobFactory</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * 自动注入所需工厂类</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="hljs-meta">@Autowired</span></span><br><span class="line"> <span class="hljs-keyword">private</span> AutowireCapableBeanFactory capableBeanFactory;</span><br><span class="line"></span><br><span class="line"> <span class="hljs-meta">@Override</span></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">protected</span> Object <span class="hljs-title">createJobInstance</span><span class="hljs-params">(TriggerFiredBundle bundle)</span> <span class="hljs-keyword">throws</span> Exception </span>{</span><br><span class="line"> <span class="hljs-comment">//调用父类的方法</span></span><br><span class="line"> Object jobInstance = <span class="hljs-keyword">super</span>.createJobInstance(bundle);</span><br><span class="line"> <span class="hljs-comment">//进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.</span></span><br><span class="line"> capableBeanFactory.autowireBean(jobInstance);</span><br><span class="line"> <span class="hljs-keyword">return</span> jobInstance;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>2) 手动创建一个调度器工厂对象<code>SchedulerFactoryBean</code>,设置一些自己业务所需的属性重点是设置<code>JobFactory</code>为第一步自定义的<code>HachiQuartzJobFactory.java</code>代码详见<code>QuartzConfiguration.java</code></p><figure class="highlight java hljs"><figcaption><span>[] [QuartzConfiguration.java]</span></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><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.scheduling.quartz.SchedulerFactoryBean;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@BelongsProject</span>: spring-boot-dynamic-quartz</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@BelongsPackage</span>: com.hachismart.config</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@Author</span>: smallodd</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@CreateTime</span>: 2019-04-15 16:52</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span>: Quartz配置类</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"><span class="hljs-meta">@Configuration</span></span><br><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QuartzConfiguration</span> </span>{</span><br><span class="line"> <span class="hljs-meta">@Bean</span></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">public</span> SchedulerFactoryBean <span class="hljs-title">schedulerFactoryBean</span><span class="hljs-params">()</span> </span>{</span><br><span class="line"> SchedulerFactoryBean factoryBean = <span class="hljs-keyword">new</span> SchedulerFactoryBean();</span><br><span class="line"> <span class="hljs-comment">//使用自定义的quartzJob 工厂类 防止不能注入的问题</span></span><br><span class="line"> factoryBean.setJobFactory(hachiQuartzJobFactory());</span><br><span class="line"> <span class="hljs-comment">/*用于Quartz集群,启动时更新已存在的Job*/</span></span><br><span class="line"> factoryBean.setOverwriteExistingJobs(<span class="hljs-keyword">true</span>);</span><br><span class="line"> <span class="hljs-comment">/*定时任务开始启动后延迟5秒开始*/</span></span><br><span class="line"> factoryBean.setStartupDelay(<span class="hljs-number">5</span>);</span><br><span class="line"> <span class="hljs-keyword">return</span> factoryBean;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="hljs-meta">@Bean</span></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">public</span> HachiQuartzJobFactory <span class="hljs-title">hachiQuartzJobFactory</span><span class="hljs-params">()</span> </span>{</span><br><span class="line"> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> HachiQuartzJobFactory();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>3) 根据<code>schedulerFactoryBean</code>获取到<code>Scheduler</code>(任务调度器)</p><p>4) 获取触发器 判断触发器是否存在(如果存在说明之前运行过但是在当前被禁用了,如果不存在说明一次都没运行过) 存在则取出出发器 重启任务 否则 新建触发器 放到任务调度器中,代码详见<code>QuartzTableService.java</code></p><figure class="highlight java hljs"><figcaption><span>[] [QuartzTableService.java]</span></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><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></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">import</span> com.hachismart.enums.ConfigEnum;</span><br><span class="line"><span class="hljs-keyword">import</span> com.hachismart.jpa.bean.QuartzConfig;</span><br><span class="line"><span class="hljs-keyword">import</span> com.hachismart.jpa.mapper.QuartzConfigMapper;</span><br><span class="line"><span class="hljs-keyword">import</span> com.hachismart.config.HachiQuartzJobConfig;</span><br><span class="line"><span class="hljs-keyword">import</span> org.quartz.*;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.scheduling.quartz.SchedulerFactoryBean;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@BelongsProject</span>: spring-boot-dynamic-quartz</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@BelongsPackage</span>: com.hachismart.service</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@Author</span>: smallodd</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@CreateTime</span>: 2019-04-15 17:20</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span>: 动态加载Scheduler service</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"><span class="hljs-meta">@Service</span></span><br><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QuartzTableService</span> </span>{</span><br><span class="line"> <span class="hljs-meta">@Autowired</span></span><br><span class="line"> <span class="hljs-keyword">private</span> SchedulerFactoryBean schedulerFactoryBean;</span><br><span class="line"></span><br><span class="line"> <span class="hljs-meta">@Autowired</span></span><br><span class="line"> <span class="hljs-keyword">private</span> QuartzConfigMapper quartzConfigMapper;</span><br><span class="line"></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(Long id, String status)</span> <span class="hljs-keyword">throws</span> Exception </span>{</span><br><span class="line"> <span class="hljs-comment">//判断是否有此ID的数据</span></span><br><span class="line"> QuartzConfig config = quartzConfigMapper.getOne(id);</span><br><span class="line"> <span class="hljs-keyword">if</span> (config == <span class="hljs-keyword">null</span>) {</span><br><span class="line"> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"未找到此定时任务"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="hljs-keyword">if</span> (<span class="hljs-string">"1"</span>.equals(status)) {</span><br><span class="line"> <span class="hljs-comment">// stop 禁用</span></span><br><span class="line"> config.setStatus(ConfigEnum.STATUS_STOP.getCode());</span><br><span class="line"> deleteJob(config);</span><br><span class="line"> } <span class="hljs-keyword">else</span> {</span><br><span class="line"> <span class="hljs-comment">//start 启用</span></span><br><span class="line"> config.setStatus(ConfigEnum.STATUS_START.getCode());</span><br><span class="line"> addJob(config);</span><br><span class="line"> }</span><br><span class="line"> quartzConfigMapper.setStatusById(config.getStatus(), config.getId());</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * 启动所有的任务</span></span><br><span class="line"><span class="hljs-comment"> *</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@return</span>: void</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startJobs</span><span class="hljs-params">()</span> </span>{</span><br><span class="line"> List<QuartzConfig> configList = quartzConfigMapper.findAll();</span><br><span class="line"> <span class="hljs-keyword">for</span> (QuartzConfig config : configList) {</span><br><span class="line"> <span class="hljs-keyword">if</span> (ConfigEnum.STATUS_START.getCode().equals(config.getStatus())) {</span><br><span class="line"> <span class="hljs-keyword">try</span> {</span><br><span class="line"> addJob(config);</span><br><span class="line"> } <span class="hljs-keyword">catch</span> (SchedulerException e) {</span><br><span class="line"> e.printStackTrace();</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="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * 修改cron表达式</span></span><br><span class="line"><span class="hljs-comment"> *</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> id</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> cronSchedule</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">updateCron</span><span class="hljs-params">(Long id, String cronSchedule)</span> </span>{</span><br><span class="line"> <span class="hljs-keyword">int</span> i = quartzConfigMapper.setScheduleById(cronSchedule, id);</span><br><span class="line"> <span class="hljs-keyword">if</span> (i <= <span class="hljs-number">0</span>) {</span><br><span class="line"> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"500!"</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 class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * 增加任务</span></span><br><span class="line"><span class="hljs-comment"> *</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addJob</span><span class="hljs-params">(QuartzConfig config)</span> <span class="hljs-keyword">throws</span> SchedulerException </span>{</span><br><span class="line"> <span class="hljs-comment">//得到调度器</span></span><br><span class="line"> Scheduler scheduler = schedulerFactoryBean.getScheduler();</span><br><span class="line"> JobKey jobKey = <span class="hljs-keyword">this</span>.getJobKey(config);</span><br><span class="line"> <span class="hljs-comment">//获得触发器</span></span><br><span class="line"> TriggerKey triggerKey = TriggerKey.triggerKey(config.getName(), config.getGroup());</span><br><span class="line"> CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);</span><br><span class="line"> <span class="hljs-comment">//判断触发器是否存在(如果存在说明之前运行过但是在当前被禁用了,如果不存在说明一次都没运行过)</span></span><br><span class="line"> <span class="hljs-keyword">if</span> (trigger == <span class="hljs-keyword">null</span>) {</span><br><span class="line"> <span class="hljs-comment">//新建一个工作任务 指定任务类型为串接进行的</span></span><br><span class="line"> JobDetail jobDetail = JobBuilder.newJob(HachiQuartzJobConfig.class).withIdentity(jobKey).build();</span><br><span class="line"> <span class="hljs-comment">//将工作添加到工作任务当中去</span></span><br><span class="line"> jobDetail.getJobDataMap().put(HachiQuartzJobConfig.SCHEDULEJOBKEY, config);</span><br><span class="line"> <span class="hljs-comment">//将cron表达式进行转换</span></span><br><span class="line"> CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(config.getCron());</span><br><span class="line"> <span class="hljs-comment">//创建触发器并将cron表达式对象给塞入</span></span><br><span class="line"> trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();</span><br><span class="line"> <span class="hljs-comment">//在调度器中将触发器和任务进行组合</span></span><br><span class="line"> scheduler.scheduleJob(jobDetail, trigger);</span><br><span class="line"> } <span class="hljs-keyword">else</span> {</span><br><span class="line"> CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(config.getCron());</span><br><span class="line"> <span class="hljs-comment">//按照新的规则进行</span></span><br><span class="line"> trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();</span><br><span class="line"> <span class="hljs-comment">//重启</span></span><br><span class="line"> scheduler.rescheduleJob(triggerKey, trigger);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * 删除任务</span></span><br><span class="line"><span class="hljs-comment"> *</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deleteJob</span><span class="hljs-params">(QuartzConfig config)</span> <span class="hljs-keyword">throws</span> SchedulerException </span>{</span><br><span class="line"> <span class="hljs-comment">//得到调度器</span></span><br><span class="line"> Scheduler scheduler = schedulerFactoryBean.getScheduler();</span><br><span class="line"> <span class="hljs-comment">//找到key值</span></span><br><span class="line"> JobKey jobKey = <span class="hljs-keyword">this</span>.getJobKey(config);</span><br><span class="line"> <span class="hljs-comment">//从触发器找到此任务然后进行删除</span></span><br><span class="line"> scheduler.deleteJob(jobKey);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * 根据name和group得到任务的key</span></span><br><span class="line"><span class="hljs-comment"> *</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">private</span> JobKey <span class="hljs-title">getJobKey</span><span class="hljs-params">(QuartzConfig config)</span> </span>{</span><br><span class="line"> <span class="hljs-keyword">return</span> getJobKey(config.getName(), config.getGroup());</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">private</span> JobKey <span class="hljs-title">getJobKey</span><span class="hljs-params">(String name, String group)</span> </span>{</span><br><span class="line"> <span class="hljs-keyword">return</span> JobKey.jobKey(name, group);</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></pre></td></tr></table></figure><p>5) 创建一个任务类需要继承<code>Job</code>,实现方法<code>execute</code>,根据反射执行对应的<code>job</code>,代码详见<code>HachiQuartzJobConfig.java</code></p><figure class="highlight java hljs"><figcaption><span>[] [HachiQuartzJobConfig.java]</span></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><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="hljs-keyword">import</span> com.hachismart.jpa.bean.QuartzConfig;</span><br><span class="line"><span class="hljs-keyword">import</span> com.hachismart.utils.TaskUtils;</span><br><span class="line"><span class="hljs-keyword">import</span> org.quartz.DisallowConcurrentExecution;</span><br><span class="line"><span class="hljs-keyword">import</span> org.quartz.Job;</span><br><span class="line"><span class="hljs-keyword">import</span> org.quartz.JobExecutionContext;</span><br><span class="line"><span class="hljs-keyword">import</span> org.quartz.JobExecutionException;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="hljs-keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="hljs-comment">/**</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@BelongsProject</span>: spring-boot-dynamic-quartz</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@BelongsPackage</span>: com.hachismart.config</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@Author</span>: smallodd</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@CreateTime</span>: 2019-04-15 16:52</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@Description</span>: 定时问题调用方法</span></span><br><span class="line"><span class="hljs-comment"> * <span class="hljs-doctag">@DisallowConcurrentExecution</span> 注解表示禁止并发执行多个相同定义的JobDetail, 但是不是禁止执行相同的任务</span></span><br><span class="line"><span class="hljs-comment"> */</span></span><br><span class="line"><span class="hljs-meta">@DisallowConcurrentExecution</span></span><br><span class="line"><span class="hljs-meta">@Component</span>(<span class="hljs-string">"hachiQuartzJobConfig"</span>)</span><br><span class="line"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HachiQuartzJobConfig</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Job</span> </span>{</span><br><span class="line"></span><br><span class="line"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String SCHEDULEJOBKEY = <span class="hljs-string">"scheduleJob"</span>;</span><br><span class="line"> <span class="hljs-meta">@Autowired</span></span><br><span class="line"> <span class="hljs-keyword">private</span> TaskUtils taskUtils;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="hljs-comment">//execute会根据cron的规则进行执行</span></span><br><span class="line"> <span class="hljs-meta">@Override</span></span><br><span class="line"> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">(JobExecutionContext jobExecutionContext)</span> <span class="hljs-keyword">throws</span> JobExecutionException </span>{</span><br><span class="line"> QuartzConfig config = (QuartzConfig) jobExecutionContext.getMergedJobDataMap().get(SCHEDULEJOBKEY);</span><br><span class="line"> taskUtils.invokMethod(config);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>经过如上描述动态修改<code>cron</code>表达式的核心以及写好了,外围的<code>crud</code>详见<code>github</code>,该项目的<code>github</code>地址为: <a href="https://github.com/smallodd/spring-boot-dynamic-quartz" target="_blank" rel="noopener">https://github.com/smallodd/spring-boot-dynamic-quartz</a> 如有帮助,烦请点击<code>start</code></p>]]></content>
<tags>
<tag> JAVA </tag>
<tag> Spring </tag>
</tags>
</entry>
<entry>
<title>一起学Java之合理的配置线程池以及线程池的监控</title>
<link href="/1781080007.html"/>
<url>/1781080007.html</url>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>使用线程池的时候,我们最迷惑的就是如何去配置线程池,一旦线程池配置不合理很可能会导致系统异常。出了异常我们就需要监控异常。下面我们一起来总结一下如何合理的配置以及如何监控。<a id="more"></a></p><h3 id="线程池的设置"><a href="#线程池的设置" class="headerlink" title="线程池的设置"></a>线程池的设置</h3><p>想要合理的配置线程池,就要先了解任务的特征,简单来讲,我们在判定任务的特征的时候可以从以下几个角度来分析</p><ol><li><p>任务的类型</p><ol><li><code>CUP</code>使用密集:这种类型的任务不易配置过多的线程,因为多了有可能会导致<code>CPU</code>资源耗尽,即配置尽可能小的线程,例如配置<code>CUP个数+1</code>个线程的 线程池。</li><li><code>IO</code>密集:由于<code>IO</code>执行需要时间,所以线程不一定是一直在执行任务,所以配置尽可能多的线程,例如配置<code>CPU个数的2倍</code>个线程的线程池</li><li><code>IO</code>、<code>CPU</code>混合密集:这种类型的,看看是否可以拆分,如果可以拆分就将任务拆分为一个<code>IO</code>密集任务和<code>CUP</code>密集任务,但是如果拆分后的两个任务执行时间相差很大就没必要拆分了。</li><li>任务是否有优先级:这种类型的任务可以使用优先级队列PriorityBlockingQueue来处理。它可以让优先级高的任务先执行。但是有一点要注意,如果设置了优先级,那么优先级低的可能永远不会执行。</li><li>任务大致的执行时间(长、适中、短):这种类型的任务,不同时间长的任务交给不同规模线程池处理,当然最懒的办法就是交给优先级队列处理,时间短的优先执行</li><li>任务是否依赖其他资源,例如第三方接口:如果依赖其他资源,表示要其他资源给的响应,等待时间越长,<code>CUP</code>空闲时间就越长,所以线程数要大些才能更好的利用<code>CPU</code>资源</li></ol></li><li><p>阻塞队列的选择<br><code>强烈建议使用有界的队列</code>,使用无界队列如果队列中任务堆积导致内存挂掉,那么会导致整个服务不可用,使用有界的队列可以通过设定好的策略来判断线程执行状况,如果其中一个线程耗时太久,队列不会堆积,系统正常运行,只需要解决到这个耗时太久的问题即可。不会影响服务的运行。</p></li></ol><h3 id="线程池的监控"><a href="#线程池的监控" class="headerlink" title="线程池的监控"></a>线程池的监控</h3><p>线程池提供了以下属性来帮我们监控</p><ol><li><code>taskCount</code>:这个参数表示线程池需要执行的任务数量。</li><li><code>completedTaskCount</code>:这个参数表示线程池在运行过程中已完成的任务数量,小于或等于`taskCount`。</li><li><code>largestPoolSize</code>:这个参数表示线程池里曾经创建过的最大线程数量。通过这个数据可以知道线程池是<br>否曾经满过。如该数值等于线程池的最大大小,则表示线程池曾经满过。</li><li><code>getPoolSize</code>:线程池的线程数量。如果线程池不销毁的话,这个数量只曾不减。</li><li><code>getActiveCount</code>:获取活动的线程数。</li><li>当然线程池也提供的方法让我们重写,他们分别是<code>beforeExecute</code>、<code>afterExecute</code>和<code>terminated</code>方法,可以在任务执行前、执行后和线程池关闭前执行一些代码来进行监控。例如,监控任务的平均执行时间、最大执行时间和最小执行时间等。这几个方法在线程池里是空方法。</li></ol><p>以上就是我们要了解的。希望读完这篇文章,可以让大家合理的准确是使用线程池。</p>]]></content>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学Java之线程池</title>
<link href="/1392887984.html"/>
<url>/1392887984.html</url>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>在开发中我们会使用多线程来提高效率,<code>Java</code>中提供了线程池,线程池是运用场景最多的并发框架,可以这么说,几乎所有需要异步或者并发执行任务的程序都可以使用线程池。合理的使用线程池<a id="more"></a>可以降低资源消耗,提高响应速度,更加方便的管理线程。</p><h3 id="线程池主要的处理流程"><a href="#线程池主要的处理流程" class="headerlink" title="线程池主要的处理流程"></a>线程池主要的处理流程</h3><p>要想了解一件事,那么我们必须先了解这件事的流程,所以我们要了解一下线程池的主要处理流程。</p><ol><li>任务提交以后,线程池判断核心线程是否都在执行任务,如果没有,就新建一个线程来执行这个任务,如果有那么进入第二步。</li><li>线程池判断工作队列中是否已满,没有,就把这个队列存储到工作队列中去,如果满了,就执行第三步。</li><li>线程池判断线程池的线程是否都处于工作状态,如果没有,就创建一个线程来执行任务,如果已经满了,就按照策略处理无法执行的任务。</li><li>主要的处理流程见下图</li></ol><p><img src="/images/%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%9A%84%E5%A4%84%E7%90%86%E6%B5%81%E7%A8%8B.jpg" alt></p><h3 id="线程池的使用"><a href="#线程池的使用" class="headerlink" title="线程池的使用"></a>线程池的使用</h3><h4 id="线程池的创建"><a href="#线程池的创建" class="headerlink" title="线程池的创建"></a>线程池的创建</h4><p>下面我们来看下线程池的使用,在<code>Java</code>中我们可以通过<code>ThreadPoolExecutor</code>来创建一个线程池,初始化线程池的时候要有几个参数(基于jdk1.8),我们一起来看下</p><ol><li>corePoolSize: 这个参数表示线程池的基本大小,根据线程池的处理流程我们可以知道,当提交一个任务到线程池中的时候,线程池会创建一个线程来执行任务,这里需要注意一点,当线程池的基本大小没满的时候,不管线程池有没有空闲,他都会创建一个线程来执行,直到线程池的基本大小满了,就不在创建了,有的同学就会问了,能不能不在提交任务的时候创建呢,当然是可以的,线程池提供了一个prestartAllCoreThreads()的方法,调用这个方法以后,线程池会提前创建并启动所有基本线程。</li><li>maximumPoolSize: 这个参数表示线程池的最大数量,简单的来说就是线程池允许创建的最大的线程数量。如果工作队列满了,线程池就会新建一个线程来执行任务,但是有一点,如果任务队列的大小是无限大的时候,这个最大值就没有用了,因为不管你有多少任务,他都会进入到任务队列中去。</li><li>keepAliveTime: 线程的保活时间,就是在线程池中有一个工作线程空闲了,这个线程可以存活多长时间,如果每个任务的执行时间比较短的话,我们可以加大线程的保活时间,这样线程的利用率就提高了</li><li>unit: 线程保活的单位,详见TimeUnit,可以是天、小时、分钟、秒、毫秒、微妙、纳秒</li><li>workQueue: 工作队列,作用是用来保存等待执行任务的阻塞队列,阻塞队列有多种下面我们来一一看下<ul><li>ArrayBlockingQueue: 看名字是不是很熟悉,像不像<code>ArrayList</code>,通过名字我们可以看出,肯定是基于数据结构的,所以呢<code>ArrayBlockingQueue</code>是一个基于数据的,有界的(可以设置队列大小)阻塞队列,这个队列按照先进先出的原则对队列中的任务进行排序</li><li>LinkedBlockingQueue: 同理,这个一看就知道是基于链表的阻塞队列,这个队列也是按照先进先出原则进行排序,由于使用的是链表,插入删除效率高,所以吞吐量是要高于<code>ArrayBlockingQueue</code>的</li><li>SynchronousQueue:这个是一个不存储元素的阻塞队列,看名字就知道,同步,这表示每一个插入操作都必须等到另一个线程的移除操作,不然插入操作就会一直阻塞</li><li>PriorityBlockingQueue: 一个支持优先级的无界阻塞队列,直到系统资源耗尽,使用的较少。</li></ul></li><li>threadFactory:用来设置创建线程的工厂,一般的都使用<code>guava</code>提供的<code>ThreadFactoryBuilder</code>来创建,例如通过<code>ThreadFactoryBuilder</code>来给线程设置名字,方便后期查问题,代码示例: <figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">public static void main(String[] args) {</span><br><span class="line"> ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 0L, TimeUnit.MILLISECONDS,</span><br><span class="line"> new LinkedBlockingDeque<>(2),new ThreadFactoryBuilder().setNameFormat("hachi-test-%d").build());</span><br><span class="line"></span><br><span class="line"> threadPoolExecutttr.prestartAllCoreThreads();</span><br><span class="line"> for (int i = 0; i <3 ; i++ {</span><br><span class="line"> threadPoolExecutor.execute(new Runnable() {</span><br><span class="line"> @Override</span><br><span class="line"> public void run() {</span><br><span class="line"></span><br><span class="line"> System.out.println("线程"+ Thread.currentThread().getName()+"执行");</span><br><span class="line"> try {</span><br><span class="line"> TimeUnit.SECONDS.sleep(1L);</span><br><span class="line"> } catch (InterruptedException e) {</span><br><span class="line"> e.printStackTrace();</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></pre></td></tr></table></figure></li></ol><p>输出示例:</p><figure class="highlight plain hljs"><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">线程hachi-test-2执行</span><br><span class="line">线程hachi-test-0执行</span><br><span class="line">线程hachi-test-1执行</span><br></pre></td></tr></table></figure><ol start="7"><li><p>handler: 表示当队列已经饱和的时候使用的策略,类型为:<code>RejectedExecutionHandler</code>即如果队列和线程池都满了就需要一种策略来处理新加入的任务。jdk提供了4钟策略来处理这种情况</p><ul><li><p>AbortPolicy:直接抛出异常,这也是<code>ThreadPoolExecutor</code>默认的策略</p></li><li><p>CallerRunsPolicy: 只要线程池未关闭,就用调用者所在的线程来执行任务,这样做的好处是可以不用丢弃任务,坏处是可能导致调用者线程的性能急剧下降</p></li><li><p>DiscardOldestPolicy: 这个就比较流氓了,当任务进来的时候,直接丢去队列里面最近的一个任务,并执行当前任务。</p></li><li><p>DiscardPolicy:不处理,丢弃掉。</p></li><li><p>通过查看jdk 源码来看上述四种策略都是在<code>ThreadPoolExecutor</code>中的静态内部类,详细代码如下</p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line"> /**</span><br><span class="line"> * A handler for rejected tasks that runs the rejected task</span><br><span class="line"> * directly in the calling thread of the {@code execute} method,</span><br><span class="line"> * unless the executor has been shut down, in which case the task</span><br><span class="line"> * is discarded.</span><br><span class="line"> */</span><br><span class="line">public static class CallerRunsPolicy implements RejectedExecutionHandler {</span><br><span class="line"> /**</span><br><span class="line"> * Creates a {@code CallerRunsPolicy}.</span><br><span class="line"> */</span><br><span class="line"> public CallerRunsPolicy() { }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * Executes task r in the caller's thread, unless the executor</span><br><span class="line"> * has been shut down, in which case the task is discarded.</span><br><span class="line"> *</span><br><span class="line"> * @param r the runnable task requested to be executed</span><br><span class="line"> * @param e the executor attempting to execute this task</span><br><span class="line"> */</span><br><span class="line"> public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {</span><br><span class="line"> if (!e.isShutdown()) {</span><br><span class="line"> r.run();</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"> * A handler for rejected tasks that throws a</span><br><span class="line"> * {@code RejectedExecutionException}.</span><br><span class="line"> */</span><br><span class="line">public static class AbortPolicy implements RejectedExecutionHandler {</span><br><span class="line"> /**</span><br><span class="line"> * Creates an {@code AbortPolicy}.</span><br><span class="line"> */</span><br><span class="line"> public AbortPolicy() { }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * Always throws RejectedExecutionException.</span><br><span class="line"> *</span><br><span class="line"> * @param r the runable task requested to be executed</span><br><span class="line"> * @param e the execuutor attempting to execute this task</span><br><span class="line"> * @throws RejectedExecutionException always</span><br><span class="line"> */</span><br><span class="line"> public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {</span><br><span class="line"> throw new RejectedExecutionException("Task " + r.toString() +</span><br><span class="line"> " rejected from " +</span><br><span class="line"> e.toString());</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"> * A handler for rejected tasks that silently discards the</span><br><span class="line"> * rejected task.</span><br><span class="line"> */</span><br><span class="line">public static class DiscardPolicy implements RejectedExecutionHandler {</span><br><span class="line"> /**</span><br><span class="line"> * Creates a {@code DiscardPolicy}.</span><br><span class="line"> */</span><br><span class="line"> public DiscardPolicy() { }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * Does nothing, which has the effect of discarding task r.</span><br><span class="line"> *</span><br><span class="line"> * @param r the runnable task requested toe executed</span><br><span class="line"> * @param e the executor attempting to execuuute this task</span><br><span class="line"> */</span><br><span class="line"> public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {</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"> * A handler for rejected tasks that discards the oldest unhandled</span><br><span class="line"> * request and then retries {@code execute}, unless the executor</span><br><span class="line"> * is shut down, in which case the task is discarded.</span><br><span class="line"> */</span><br><span class="line">public static class DiscardOldestPolicy implements RejectedExecutionHandler {</span><br><span class="line"> /**</span><br><span class="line"> * Creates a {@code DiscardOldestPolicy} for the given executor.</span><br><span class="line"> */</span><br><span class="line"> public DiscardOldestPolicy() { }</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line"> * Obtains and ignores the next task that the executor</span><br><span class="line"> * would otherwise execute, if one is immediately available,</span><br><span class="line"> * and then retries execution of task r, unless the executor</span><br><span class="line"> * is shut down, in which case task r is instead discarded.</span><br><span class="line"> *</span><br><span class="line"> * @param r the runnable task requested to be executed</span><br><span class="line"> * @param e the executor attempting to execute this task</span><br><span class="line"> */</span><br><span class="line"> public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {</span><br><span class="line"> if (!e.isShutdown()) {</span><br><span class="line"> e.getQueue().poll();</span><br><span class="line"> e.execute(r);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>所以我们也可以手动实现<code>RejectedExecutionHandler</code>接口来自定义策略,例如记录log,或者任务重启机制等</p></li></ul></li></ol><h4 id="向线程池中提交任务"><a href="#向线程池中提交任务" class="headerlink" title="向线程池中提交任务"></a>向线程池中提交任务</h4><p>在<code>ThreadPoolExecutor</code>中提供了两种方法想线程池中提交任务,分别是execute()和submit()。下面我们来了解一下这个方法</p><ol><li><p>execute: 通过查看jdk源码我们不难发现<code>execute</code>方法的入参是一个Runnable()对象,但是是没有回参的所以我们无法判断任务是否被线程池执行成功。示例代码:</p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">threadPoolExecutor.execute(new Runnable() {</span><br><span class="line"> @Override</span><br><span class="line"> public void run() {</span><br><span class="line"></span><br><span class="line"> System.out.println("线程"+ Thread.currentThread().getName()+"执行");</span><br><span class="line"> try {</span><br><span class="line"> TimeUnit.SECONDS.sleep(1L);</span><br><span class="line"> } catch (InterruptedException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> });</span><br></pre></td></tr></table></figure></li><li><p>submit: 通过查看jdk源码我们可以发现 submit方法是来源于接口<code>ExecutorService</code>,<code>AbstractExecutorService</code>实现了<code>ExecutorService</code>,<code>ThreadPoolExecutor</code>继承了<code>AbstractExecutorService</code>。 这个方法是可以返回一个Future类型,通过这个回参的get()方法可以获取返回值。</p><ul><li>get()方法会阻塞当前线程直到任务完成</li><li>get(long timeout,TimeUnit unit)会根据传入的时间来阻塞一段时间然后立即返回,这个时候任务很可能未完成 </li></ul></li></ol><p>下面我们看下<code>submit</code>方法的代码</p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * @throws RejectedExecutionException {@inheritDoc}</span><br><span class="line"> * @throws NullPointerException {@inheritDoc}</span><br><span class="line"> */</span><br><span class="line">public Future<?> submit(Runnable task) {</span><br><span class="line"> if (task == null) throw new NullPointerException();</span><br><span class="line"> RunnableFuture<Void> ftask = newTaskFor(task, null);</span><br><span class="line"> execute(ftask);</span><br><span class="line"> return ftask;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @throws RejectedExecutionException {@inheritDoc}</span><br><span class="line"> * @throws NullPointerException {@inheritDoc}</span><br><span class="line"> */</span><br><span class="line">public <T> Future<T> submit(Runnable task, T result) {</span><br><span class="line"> if (task == null) throw new NullPointerException();</span><br><span class="line"> RunnableFuture<T> ftask = newTaskFor(task, result);</span><br><span class="line"> execute(ftask);</span><br><span class="line"> return ftask;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @throws RejectedExecutionException {@inheritDoc}</span><br><span class="line"> * @throws NullPointerException {@inheritDoc}</span><br><span class="line"> */</span><br><span class="line">public <T> Future<T> submit(Callable<T> task) {</span><br><span class="line"> if (task == null) throw new NullPointerException();</span><br><span class="line"> RunnableFuture<T> ftask = newTaskFor(task);</span><br><span class="line"> execute(ftask);</span><br><span class="line"> return ftask;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>可以看到有三个submit方法。但是只有实现了<code>Callable</code>接口才能有返回值, <code>Runnable</code>是没有的,即<code>submit(Runnable task)</code>返回的值调用get方法后会返回一个<code>null</code>。而<code>submit(Runnable task, T result)</code>能通过传入的载体<code>result</code>间接获得线程的返回值,如果执行失败就会获取到异常,如果执行成功就会拿到之前定义好的值<br>下面我们介绍一下<code>submit(Callable<T> task)</code> 示例代码详见: </p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">public static void main(String[] args) throws ExecutionException, InterruptedException {</span><br><span class="line"> ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 0L, TimeUnit.MILLISECONDS,</span><br><span class="line"> new LinkedBlockingDeque<>(2),new ThreadFactoryBuilder().setNameFormat("hachi-test-%d").build());</span><br><span class="line"></span><br><span class="line"> threadPoolExecutor.prestartAllCoreThreads();</span><br><span class="line"></span><br><span class="line"> for (int i = 0; i <3 ; i++) {</span><br><span class="line"> Callable<HttpClientResultBean> callable = new Callable<HttpClientResultBean>() {</span><br><span class="line"> public HttpClientResultBean call() throws Exception {</span><br><span class="line"> System.out.println("线程"+ Thread.currentThread().getName()+"执行");</span><br><span class="line"> return new HttpClientResultBean();</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> Future<HttpClientResultBean> future= threadPoolExecutor.submit(callable);</span><br><span class="line"> System.out.println(JsonUtils.obj2Json(future.get()));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="关闭线程池"><a href="#关闭线程池" class="headerlink" title="关闭线程池"></a>关闭线程池</h4><p>通过上述操作我们创建了线程池,并且向线程池中新增了任务,那么我们如何关闭线程池呢?jdk提供了<code>shutdown</code>和<code>shutdownNow</code>两个方法来关闭线程池。原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务<br>可能永远无法终止。那么他们有啥区别呢?</p><ol><li>shutdown: 仅仅是将线程池的状态设置成<code>SHUTDOWN</code>状态,然后中断没有正在执行的任务线程</li><li>shutdownNow:首先将线程池的状态设置成`STOP`,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表</li></ol><p>注意:</p><ul><li>只要调用了两个方法的任意一个,<code>isShutdown</code>方法就会返回<code>true</code>。当所有的任务<br>都已关闭后,才表示线程池关闭成功,这时调用<code>isTerminaed</code>方法会返回<code>true</code>。至于应该调用哪<br>一种方法来关闭线程池,应该由提交到线程池的任务特性决定,通常调用<code>shutdown</code>方法来关闭<br>线程池,如果任务不一定要执行完,则可以调用<code>shutdownNow</code>方法。</li></ul>]]></content>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>熊猫翻滚之deepin的使用</title>
<link href="/38999229.html"/>
<url>/38999229.html</url>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>本文假定你知道什么是 <code>熊猫翻滚</code> ,主要描述的是 <code>熊猫翻滚</code> 在 <code>ddepin</code> 上的使用,因为官网上的教程是没有讲 <code>deepin</code> 上是咋用的,导致 <code>deepin</code> 的用户花钱不能使用。所以本文主要解决这个问题。</p><a id="more"></a><h3 id="所需工具"><a href="#所需工具" class="headerlink" title="所需工具"></a>所需工具</h3><ol><li>Clash<ul><li>Clash是一款开源免费的代理软件</li><li>下载地址:<code>https://github.com/Dreamacro/clash/releases</code></li></ul></li></ol><p>2. <code>熊猫翻滚</code>上维护的<code>Clash</code>配置文件</p><ol start="3"><li><p>一个<code>deepin</code>系统</p></li><li><p>一个浏览器</p></li></ol><h3 id="开始配置"><a href="#开始配置" class="headerlink" title="开始配置"></a>开始配置</h3><ol><li><p>运行下载好的<code>Clash</code> 初次运行会在 <code>~/.config/clash/</code> 文件夹下生成俩文件 <code>config.yaml</code> 、<code>Country.mmdb</code></p><ul><li><code>config.yaml</code>存放着服务器及规则等信息</li><li><code>Country.mmdb</code> 很显然是个数据库文件</li></ul></li><li><p>下载<code>熊猫翻滚</code>维护的配置文件,并打开把内容拷贝到<code>~/.config/clash/config.yaml</code>文件中</p></li><li><p>重启<code>Clash</code>。 如果是用终端打开的,那么只需要Ctrl+C即可 如果是直接运行就需要查询到<code>Clash</code>运行的pid 然后kill掉它</p></li><li><p>这个时候就需要打开<code>http://clash.razord.top/</code>这个网址可以看到配置好的路线</p></li><li><p>在<code>deepin</code>中设置代理。 在 设置>网络>系统代理>手动 中按照yml配置文件中设置的端口进行配置。至此便可通过<code>Clash</code>上网。</p></li></ol><p>基本配置就是这样了,那么每次电脑重启都要手动启动<code>Clash</code>岂不是很麻烦,所以我们需要开机自动启动。</p><h3 id="如何配置开机自启Clash"><a href="#如何配置开机自启Clash" class="headerlink" title="如何配置开机自启Clash"></a>如何配置开机自启Clash</h3><p>要解决这个问题我们需要知道在<code>deepin</code>中图标文件的咋写,图标文件存放的位置</p><ol><li><p>图标文件的位置位于 <code>/usr/share/applications/</code></p></li><li><p>图标文件咋写(详情见代码块)</p><ul><li>图标文件是以desktop为拓展名的文件 </li></ul></li></ol><pre><code><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">[Desktop Entry]</span><br><span class="line">Categories=Network;</span><br><span class="line">Comment=clash</span><br><span class="line">Exec=/opt/clash/clash-linux-amd64 %U</span><br><span class="line">Icon=/opt/clash/clash.png</span><br><span class="line">Name=clash</span><br><span class="line">Terminal=false</span><br><span class="line">Type=Application</span><br><span class="line">X-Deepin-Vendor=user-custom</span><br></pre></td></tr></table></figure></code></pre>]]></content>
</entry>
<entry>
<title>一起学Java之wait、notify 和 notifyAll</title>
<link href="/1747159659.html"/>
<url>/1747159659.html</url>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本文主要描述了wait、notify 和 notifyAll 的作用,超级无敌枯燥,需要耐心看完,并多读几遍。</p><a id="more"></a><h2 id="什么是-wait、notify-和-notifyAll"><a href="#什么是-wait、notify-和-notifyAll" class="headerlink" title="什么是 wait、notify 和 notifyAll"></a>什么是 wait、notify 和 notifyAll</h2><h3 id="wait"><a href="#wait" class="headerlink" title="wait"></a>wait</h3><ol><li>暂停某个线程,实现线程等待,前提是必须先获得锁(因为wait主要做的事情就是把锁释放了,并等待唤醒)</li><li>同一个对象的wait方法可以被不同线程执行,所以一个对象可能有多个等待线程。</li><li>wait是原子操作的方法,当wait执行时,释放对象内部锁,进行等待,当符合条件的时候,会重新获得对象的内部锁,再继续判断条件往下执行,如果不符合条件就会重新进行wait.直到条件成立,执行完目标动作这个方法才算完成.</li></ol><h3 id="notify-和-notifyAll"><a href="#notify-和-notifyAll" class="headerlink" title="notify 和 notifyAll"></a>notify 和 notifyAll</h3><h4 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h4><ol><li>notify/notifyAll所在的线程叫做通知线程,主要作用是唤醒线程</li><li>执行notify之后,通知唤醒该对象相关的一个线程(notifyAll线程唤醒相关的所有线程)</li><li>待线程收到通知,并申请获得对象的锁之后,该等待线程会从该对象的wait set等待集中移除</li><li>notify 和 notifyAll 都是唤醒线程,唤醒之后都是去竞争一个对象的内部锁,两者有什么区别呢,这就要从Java的锁模型开始说起了。synchronized大家都很熟悉了,JVM会为使用synchronized的对象维护俩集合锁池(洋文: Entry Set)和等待池(洋文: Wait Set)</li></ol><h4 id="详解"><a href="#详解" class="headerlink" title="详解"></a>详解</h4><ol><li><p>当对象已经有一个线程(姑且叫线程A)获得了对象锁,另一个线程(你就叫线程B吧)也想获得这个对象的对象锁时,线程B发现这个对象的对象锁被线程A这个傻屌获取了,线程B气的没办法只能去锁池,此时的线程B处于BLOCKED状态。等过了一会儿,线程A突然执行了wait,释放了对象锁,这个时候线程A就会进入等待池,并且这时候的线程A处于WAITING状态。这时候JVM大佬通知锁池,有一个锁释放了,然后线程B一看正好是自己要获得的锁那么这个时候线程B就会由原来的BLOCKED转变为RUNNABLE。要知道,线程B想要获得对象锁有俩条件,一个是对象锁被释放,一个是自己处于RUNNABLE状态。都符合。那就可以去竞争这个对象锁了。优先级高的线程竞争到对象锁的概率大。如果线程B没有竞争到锁,那就继续在锁池中等待锁的释放。</p></li><li><p>上述情况主要讲的是锁池里面的线程变化情况。那么等待池里面的状态如何变化呢。实际上是差不多的,当线程A调用wait的时候线程A进入等待,池线程的状态就从WAITING,线程B开始,当线程B调用notify 或 notifyAll 的时候线程A就可以重新将状态变为RUNNABLE。如果遇到资源竞争,那么刚刚从等待池里面出来的线程就会到锁池里面。</p></li><li><p>了解了上面的骚操作以后,我们来谈谈notify 和 notifyAll的区别,有的童鞋会说很简单啊,notify是唤醒一个线程,notifyAll是唤醒所有线程。都是唤醒都是拿到一个锁。其实不然,里面还是有许多说道的。例如有一个场景俩生产者、俩消费者、一个资源。消费者线程1去拿资源发现为null那么他就会 wait 进入等待池,消费者2 去拿资源,也发现是null,他也进入等待池,这时候生产者1,生产者2去竞争锁,不巧生产者1获得了锁,去生产了资源,生产者2继续在锁池里面等待。生产者1执行完了这次任务后就挂了。生产者1假设使用了notify唤醒一个线程,这时候唤醒了消费者1,但是不要忘记了生产者2也要用到这把锁,不巧,生产者2竞争到了这把锁,当他满怀期待的去生产资源的时候,ok资源满了。这下,生产者2只能wait了,进入了等待池。锁池里面的消费者1、消费者2会去竞争这把锁,假设消费者1拿到了,去消费了,并调用notify。这时候如果唤醒生产者2,那么没毛病,继续正常走,但是™如果唤醒了消费者2,消费者2一看资源为空,继续wait。得由于没有线程notify,俩二货就会一直在等待,形成线程死锁。但是,如果使用notifyAll就可以避免这种麻烦。因为不管什么时候,所有的线程都会从等待池到锁池里面。都有机会去竞争锁.</p></li><li><p>总结一下,大致意思就是说 建议使用notifyAll 因为notify有一定几率会导致死锁。不管相对而言notify比notifyAll更加省资源。</p></li></ol><p>5.为什么 wait,notify 和 notifyAll 是在 Object 类中定义的而不是在 Thread 类中定义呢?原因主要有以下几点</p><ul><li>通过上述的描述我们知道 wait、notify 和 notifyAll 是两个线程之间的通信机制,因为要确保每个对象都有这个机制,所以声明到Object中去</li><li>是对象上锁,然后线程等待,而不是线程之间相互知道哪个线程上的锁,然后去请求锁释放</li></ul>]]></content>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>浅谈app中数据收集</title>
<link href="/3860430980.html"/>
<url>/3860430980.html</url>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>数据,一个在代码生涯中必不可少的成员.在一个app运营的时候一定要监控和收集大量的数据作为分析的资本.可以说数据即一切.那么哪些数据是需要我们关心并且去收集 统计 近而分析他呢.</p><a id="more"></a><p>下面我们一起来看下.</p><h3 id="数据来源"><a href="#数据来源" class="headerlink" title="数据来源"></a>数据来源</h3><p>对于一个app来说,数据来源大致分为两种</p><ul><li>app本地数据<ul><li>app本地数据,例如用户操作app时在app上的操作数据 app运行时产生的数据(包括异常数据)等</li></ul></li><li>app线上数据<ul><li>app在运行时免不了与服务端进行交互,交互就要产生数据0例如app请求服务端是服务端进行了怎样的流程 产生了怎样的数据,达到了怎样的结果等.</li></ul></li><li>app的下载数据</li></ul><p>本文主要针对app本地数据进行阐述</p><h3 id="app本地数据的分类"><a href="#app本地数据的分类" class="headerlink" title="app本地数据的分类"></a>app本地数据的分类</h3><ul><li>页面曝光 即当前屏幕页面上有哪些模块(内容)</li><li>页面信息 即用户进入了那一页</li><li>埋点行为 即用户点击了哪些</li><li>app激活数据 即有哪些手机安装了app</li></ul><h3 id="什么时候上报app本地数据"><a href="#什么时候上报app本地数据" class="headerlink" title="什么时候上报app本地数据"></a>什么时候上报app本地数据</h3><p>app端在什么时候上报数据呢?用户在使用app过程中肯定会出现网络不好的情况,那么我们如何保证在没有网络的情况下准确上报数据呢?很简单,持久化到本地呗,那么我们什么时候开始上报这些数据呢?通常来讲,用户使用app的时候经常会做以下操作: </p><ul><li>用户打开app</li><li>用户在app界面按下home键</li><li>用户在切换应用</li></ul><p>既然多数app都会进行这三项操作,那么我们可以通过上述时机来上报app本地数据,这样做确保了数据的准确性</p><h3 id="收集哪些数据"><a href="#收集哪些数据" class="headerlink" title="收集哪些数据"></a>收集哪些数据</h3><p>既然要收集数据,那肯定要确定收集哪些.上面我们有提到了app本地数据的分类那我们就按照分类来一一说明</p><ul><li>页面曝光</li></ul><table><thead><tr><th>收集的信息</th><th>说明</th></tr></thead><tbody><tr><td>上报方式</td><td></td></tr><tr><td>用户id</td><td>用来确定是哪个用户进行了操作</td></tr><tr><td>曝光屏数</td><td>当前页在第几屏幕曝光出数据的</td></tr><tr><td>曝光内容id</td><td></td></tr><tr><td>曝光内容名称</td><td></td></tr><tr><td>曝光时间</td><td></td></tr><tr><td>手机唯一标识</td><td>用来区分手机</td></tr><tr><td>app版本</td><td></td></tr><tr><td>app平台</td><td></td></tr><tr><td>页面id</td><td></td></tr><tr><td>页面名称</td><td></td></tr><tr><td>手机厂商</td><td></td></tr><tr><td>手机型号</td><td></td></tr><tr><td>系统id(名称)</td><td></td></tr><tr><td>网络类型</td><td>打开页面时候的网络类型(WiFi 移动4g 联通4g 等)</td></tr><tr><td>网络运行商</td><td>移动 电信 联通 等</td></tr><tr><td>ip</td><td>打开页面时的外网ip</td></tr><tr><td>上报时间</td><td>注意和曝光时间的区别,曝光时间不一定是上报时间</td></tr></tbody></table><ul><li>页面信息</li></ul><table><thead><tr><th>收集的信息</th><th>说明</th></tr></thead><tbody><tr><td>上报方式</td><td></td></tr><tr><td>用户id</td><td>用来确定是哪个用户进行了操作</td></tr><tr><td>页面url</td><td></td></tr><tr><td>手机唯一标识</td><td></td></tr><tr><td>打开页面时间</td><td></td></tr><tr><td>页面id</td><td></td></tr><tr><td>页面类型</td><td></td></tr><tr><td>上一页页面id</td><td></td></tr><tr><td>上一页页面类型</td><td></td></tr><tr><td>app版本</td><td></td></tr><tr><td>app平台</td><td></td></tr><tr><td>页面id</td><td></td></tr><tr><td>页面名称</td><td></td></tr><tr><td>手机厂商</td><td></td></tr><tr><td>手机型号</td><td></td></tr><tr><td>系统id(名称)</td><td></td></tr><tr><td>网络类型</td><td>打开页面时候的网络类型(WiFi 移动4g 联通4g 等)</td></tr><tr><td>网络运行商</td><td>移动 电信 联通 等</td></tr><tr><td>ip</td><td>打开页面时的外网ip</td></tr><tr><td>上报时间</td><td></td></tr></tbody></table><ul><li>埋点行为</li></ul><table><thead><tr><th>收集的信息</th><th>说明</th></tr></thead><tbody><tr><td>上报方式</td><td></td></tr><tr><td>用户id</td><td>用来确定是哪个用户进行了操作</td></tr><tr><td>手机唯一标识</td><td></td></tr><tr><td>行为名称</td><td>也就是点击了哪个按钮之类的</td></tr><tr><td>行为编码</td><td></td></tr><tr><td>行为触发时间</td><td></td></tr><tr><td>行为结束时间</td><td></td></tr><tr><td>页面id</td><td></td></tr><tr><td>页面类型</td><td></td></tr><tr><td>app版本</td><td></td></tr><tr><td>app平台</td><td></td></tr><tr><td>页面id</td><td></td></tr><tr><td>页面名称</td><td></td></tr><tr><td>手机厂商</td><td></td></tr><tr><td>手机型号</td><td></td></tr><tr><td>系统id(名称)</td><td></td></tr><tr><td>网络类型</td><td>打开页面时候的网络类型(WiFi 移动4g 联通4g 等)</td></tr><tr><td>网络运行商</td><td>移动 电信 联通 等</td></tr><tr><td>ip</td><td>打开页面时的外网ip</td></tr><tr><td>上报时间</td><td></td></tr></tbody></table><ul><li>app激活数据</li></ul><table><thead><tr><th>收集的信息</th><th>说明</th></tr></thead><tbody><tr><td>上报方式</td><td></td></tr><tr><td>激活时间</td><td></td></tr><tr><td>手机唯一标识</td><td></td></tr><tr><td>手机厂商</td><td></td></tr><tr><td>手机型号</td><td></td></tr><tr><td>系统id(名称)</td><td></td></tr><tr><td>网络类型</td><td>打开页面时候的网络类型(WiFi 移动4g 联通4g 等)</td></tr><tr><td>网络运行商</td><td>移动 电信 联通 等</td></tr><tr><td>ip</td><td>打开页面时的外网ip</td></tr><tr><td>上报时间</td><td></td></tr></tbody></table><p>通过上述,我们应该对什么时候app数据收集 以及采集哪些数据有了一定的认识.希望本文可以帮助到大家.</p>]]></content>
</entry>
<entry>
<title>一起学MySQL之MySQL简介</title>
<link href="/2769782386.html"/>
<url>/2769782386.html</url>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本文主要讲的是MySQL的一些知识,那么,MySQL是什么呢?下面我们来了解一下</p><a id="more"></a><h3 id="什么是MySQL"><a href="#什么是MySQL" class="headerlink" title="什么是MySQL"></a>什么是MySQL</h3><p>MySQL是一个关系型数据库,是Oracle公司旗下的,MySQL是世界上最流行的关系数据库之一,在开发中经常使用,别问为什么 因为免费</p><h3 id="MySQL中的数据类型"><a href="#MySQL中的数据类型" class="headerlink" title="MySQL中的数据类型"></a>MySQL中的数据类型</h3><h4 id="整数类型"><a href="#整数类型" class="headerlink" title="整数类型"></a>整数类型</h4><p>整数类型,主要包括的数据类型如下表,任何的整数类型都可以加上UNSIGNED属性,这个属性是干什么的呢,这个属性表示无符号,也就是说不管正整数负整数进入数据库的都是正整数。正数类型是可以定义长度的例如bigint(20)表示长度为20的整数类型。这里还要介绍一个属性ZEROFILL,这个属性表示补零,经常和UNSIGNED配合使用,例如int(3),如果使用了UNSIGNED ZEROFILL属性,插入数据为7的话,数据库存的就是007</p><table><thead><tr><th>类型名称</th><th>说明</th></tr></thead><tbody><tr><td>tinyint</td><td>很小的整数(8位二进制,一个字节)</td></tr><tr><td>smallint</td><td>小的整数(16位二进制,两个字节)</td></tr><tr><td>mediumint</td><td>中等大小的整数(24位二进制,三个字节)</td></tr><tr><td>int</td><td>普通大小的整数(32位二进制,四个字节)</td></tr><tr><td>bigint</td><td>很大的整数(64位二进制,八个字节)</td></tr></tbody></table><h4 id="小数类型"><a href="#小数类型" class="headerlink" title="小数类型"></a>小数类型</h4><p>小数类型包括的数据类型如下表,decimal可以存储比bigint还要大的整数,能存储精确的小数,在不指定精度的情况下,默认为(10,0),float、double都是有取值范围的,支持使用标准的浮点进行近似计算,在不指定精度时,默认会按照实际的精度来显示。根据经验,精度高的效率低,效率高的精度低。</p><table><thead><tr><th>类型名称</th><th>说明</th></tr></thead><tbody><tr><td>float</td><td>单精度浮点数</td></tr><tr><td>double</td><td>双精度浮点数</td></tr><tr><td>decimal</td><td>压缩严格的定点数</td></tr></tbody></table><h4 id="日期类型"><a href="#日期类型" class="headerlink" title="日期类型"></a>日期类型</h4><p>日期类型,如果追求效率,不在乎2038年的时间范围的话,那就使用timestamp,因为空间效率直接把datetime甩了十几条街,如果需要存储微妙,那建议用bigint存储,如果不考虑效率,那最好直接datetime,简单粗暴易维护,不必担心2038年的问题,timestamp有一个特性就是自动更新。</p><table><thead><tr><th>类型名称</th><th>说明</th></tr></thead><tbody><tr><td>year</td><td>yyyy(1901~2155)</td></tr><tr><td>time</td><td>HH:mm:ss -838:59:59 ~ 838:59:59</td></tr><tr><td>datetime</td><td>yyyy-MM-DD HH:mm:ss 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59</td></tr><tr><td>timestamp</td><td>yyyy-MM-DD HH:mm:ss 1970-01-01 00:00:00 ~ 2038-01-19 3:14:07 |</td></tr></tbody></table><h4 id="文本二进制类型"><a href="#文本二进制类型" class="headerlink" title="文本二进制类型"></a>文本二进制类型</h4><p>数据类型如下,对于字符串类型,能用char的不要用varchar,varchar中会存储字符串的长度。当列长度小于255字节时,使用1字节,当大于255的时候就需要两个字节表示了,当char或者varchar存储的内容超出设置的长度时,内容会被截断。cha是根据定义的字符串的长度分配内存空间的。</p><table><thead><tr><th>类型名称</th><th>说明</th></tr></thead><tbody><tr><td>char</td><td>可定义长度(0~255之间)</td></tr><tr><td>varchar</td><td>可定义长度(0~65535之间)</td></tr><tr><td>tinyblob</td><td>允许长度0~255字节</td></tr><tr><td>blog</td><td>允许长度0~65535字节</td></tr><tr><td>mediumblog</td><td>允许长度0~167772150字节</td></tr><tr><td>longblob</td><td>允许长度0~4294967295字节</td></tr><tr><td>tinytext</td><td>允许长度0~255字节</td></tr><tr><td>text</td><td>允许长度0~65535字节</td></tr><tr><td>mediumtext</td><td>允许长度0~167772150字节</td></tr><tr><td>longtext</td><td>允许长度0~4294967295字节</td></tr><tr><td>varbinary</td><td>可定义长度允许0~定义长度之间的字节</td></tr></tbody></table><h3 id="MySQL的索引"><a href="#MySQL的索引" class="headerlink" title="MySQL的索引"></a>MySQL的索引</h3><ol><li>索引(Index)是帮助MySQL高效获取数据的数据结构,大概就是可以帮助快速查找的一种数据结构。那么为什么要使用索引呢,很明显就是为了快,为了提高检索 效率,降低服务器的io成本,降低了CPU的消耗。缺点是每次对表进行更新操作、插入操作、删除操作都要保存一下索引,数据量大索引也大。</li><li>索引的类型</li></ol><table><thead><tr><th>类型名称</th><th>说明</th></tr></thead><tbody><tr><td>主键索引</td><td>不允许重复,不允许为null</td></tr><tr><td>普通索引</td><td>无唯一性限制,基本索引,允许为null</td></tr><tr><td>唯一索引</td><td>不允许为null,数据列不允许重复</td></tr><tr><td>全文索引</td><td>一般搜索引擎使用的技术</td></tr></tbody></table><ol start="3"><li><p>索引的算法</p><ul><li>btree<ul><li>btree是mysql默认的索引算法,他可以被用在比较运算符上(例如大于、小于、大于等于、between…等等)也可以用在like,但是like有限制,只作用于匹配不以通配符开头的数据类似与这样的写法 like ‘small%’,这样的写法可以使用索引,但是 like ‘%odd’这种就不会使用索引了</li></ul></li><li>hash算法<ul><li>hash算法只能作用于比较运算符,因为主要是基于Hash算法所以检索效率要比btree索引要高</li></ul></li></ul></li><li><p>创建索引的原则</p><ul><li>查询较为频繁的字段适合建立索引</li><li>更新频繁的字段不适合做索引</li><li>关联字段一定建索引</li><li>索引尽量只更新不新建,例如原来有个索引a,现在要再加一个索引(a,b),那么就更新这个索引就可以</li><li>数据类型为text、blog的列不要建立索引</li><li>区分度低的不适合建立索引,例如支付状态(待支付、支付中、已支付、已退款。至少有这几种状态区分度极低)</li><li>最左前缀匹配原则(组合索引经常用到),MySQL会从左到右匹配,直到匹配到范围查询(>、<、between、like…等)就会停止使用索引,例如有一个混合索引的顺序为(a,b,c) 当sql为 a=1 and b>2 and c=3 的时候 a和b的索引都会用到c的索引就不会用到了,那么怎么优化呢,就把顺序调整一下由原来的(a,b,c)改成(a,c,b),这样三个索引就都可以用到了</li><li>非空字段才能加索引,因为含空值的列在MySQL中很难优化</li><li>索引字段越小越好</li></ul></li></ol><h3 id="MySQL的存储引擎"><a href="#MySQL的存储引擎" class="headerlink" title="MySQL的存储引擎"></a>MySQL的存储引擎</h3><ol><li>Innodb: 支持ACID的事物支持,提供表级锁、行级锁,不支持全文索引,支持Hash索引,是我们经常用的存储引擎</li><li>MyIASM: 不支持事物,不支持行级锁,但是存储空间少,查询效率高,不支持Hash索引,支持全文索引</li><li>MEMORY: 数据存储在内存里面,数据处理快,但是安全性低</li></ol><h3 id="事物的ACID"><a href="#事物的ACID" class="headerlink" title="事物的ACID"></a>事物的ACID</h3><ol><li>原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;</li><li>一致性: 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;</li><li>隔离性: 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;</li><li>持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。</li></ol><h3 id="MySQL的explain"><a href="#MySQL的explain" class="headerlink" title="MySQL的explain"></a>MySQL的explain</h3><ol><li>作用:查看sql语句的执行计划,包含了这条sql查询了哪些表,查询这些表的顺序是什么,使用了哪种方式查询,扫描了多少行等</li><li>执行计划字段的含义</li></ol><table><thead><tr><th>字段名称</th><th>说明</th></tr></thead><tbody><tr><td>id</td><td>表示sql的执行顺序</td></tr><tr><td>select_type</td><td>查询类型</td></tr><tr><td>table</td><td>查询的表名</td></tr><tr><td>type</td><td>访问类型</td></tr><tr><td>possible_keys</td><td>可能使用的索引</td></tr><tr><td>key</td><td>实际使用的索引</td></tr><tr><td>key_length</td><td>索引长度</td></tr><tr><td>ref</td><td>上述表的链接匹配条件</td></tr><tr><td>rows</td><td>返回结果集的数目</td></tr><tr><td>extra</td><td>一些说明</td></tr></tbody></table><p>3.字段详解</p><ul><li>id <ul><li>id相同的执行顺序从上到下</li><li>id不同的id越大优先级越高</li><li>id为null的时候是表示这是一个结果集,不需要查询</li></ul></li><li>select_type<ul><li>SIMPLE: 简单查询,不包含子查询或者连接查询</li><li>PRIMARY: 子查询的最外面一层的查询就是PRIMARY</li><li>SUBQUERY: where字句中包含的子查询</li><li>DERIVED: from 中包含的查询</li><li>UNION: union后查询的语句</li><li>UNION RESULT:UNION中获取结果集</li></ul></li><li>type<ul><li>ALL: 全表扫描</li><li>index: 遍历索引查找</li><li>range: 在索引的范围内查询</li><li>index_subquery: 在子查询中使用ref</li><li>unique_subquery: 在子查询中使用 eq_ref</li><li>ref_or_null: 对null进行索引优化的ref</li><li>fulltext: 使用全文索引</li><li>ref: 使用非唯一索引查找数据</li><li>eq_ref: 在join查询中使用PRIMARY KEYorUNIQUE NOT NULL索引关联</li></ul></li><li>possible_keys <ul><li>查询字段中如果有索引就会被列出来,如果为null就看看sql是否需要优化</li></ul></li><li>key <ul><li>实际索引,没有用到就是null</li></ul></li><li>key_length<ul><li>索引的长度,这个没别的意思</li></ul></li><li>ref<ul><li>该表的连接匹配条件,就是那些列或者常量被用于查找索引列上的值</li></ul></li><li>rows<ul><li>扫描行数,并不一定准确</li></ul></li><li>extra<ul><li>Using index 使用覆盖索引</li><li>Using where 使用where来过滤</li><li>Using filesort 使用文件排序,使用非索引的列进行排序的时候出现,超级无敌消耗性能,一旦见到就要优化</li><li>Using temporary 使用临时表,尽量做优化</li></ul></li></ul><p>4. sql目标</p><ul><li>至少要达到range级别,要求达到ref级别,最好是consts级别</li><li>consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。</li><li>ref 指的是使用普通的索引</li><li>range 对索引进行范围检索</li></ul>]]></content>
</entry>
<entry>
<title>玩转spring之Factory(工厂模式)</title>
<link href="/452468995.html"/>
<url>/452468995.html</url>
<content type="html"><![CDATA[<h4 id="Factory模式"><a href="#Factory模式" class="headerlink" title="Factory模式"></a>Factory模式</h4><p>1.工厂模式也是我们编程中使用的最广泛的设计模式之一,工厂模式主要用来实例化对象,代替new操作。 </p><a id="more"></a><h4 id="工厂模式的简单实现"><a href="#工厂模式的简单实现" class="headerlink" title="工厂模式的简单实现"></a>工厂模式的简单实现</h4><p>1.举这样一个例子,假如有一个大老板,需要买一辆车,但是他并不知道现在市面上有些什么车,他来到汽车销售中心,对招待说,我有这么些钱,我要买车,你看这办吧,这个时候招待就会根据老板具体有多少钱而向他销售不同价位款式的汽车。下面我们用代码来模拟 </p><p>2.首先,定义一个接口Car </p><p><img src="/images/20191028-142927.png" alt></p><p>3.创建多个Car接口的实现类 </p><p><img src="/images/20191028-143016.png" alt></p><p>4.实现CarFactory </p><p><img src="/images/20191028-143135.png" alt></p><p>5.main方法测试 </p><p><img src="/images/20191028-143210.png" alt></p><p>6.在该工厂模式的简单实现中,可以发现工厂模式使用时的一些特点 </p><ul><li>在编码时不能预见需要创建哪一种类的实例 </li><li>一个类使用它的子类来创建对象 </li><li>开发人员不希望将创建了哪个类的实例以及如何创建实例的信息暴露给外部程序 </li></ul>]]></content>
<categories>
<category> 玩转spring </category>
</categories>
<tags>
<tag> spring </tag>
</tags>
</entry>
<entry>
<title>玩转spring之Singleton(单例模式)</title>
<link href="/44388.html"/>
<url>/44388.html</url>
<content type="html"><![CDATA[<h5 id="Singleton模式简介"><a href="#Singleton模式简介" class="headerlink" title="Singleton模式简介"></a>Singleton模式简介</h5><p>1.单例模式是我们编程中使用最广泛的设计模式之一,作用就是保证在应用中,一个类只有一个实例存在 </p><p>2.单例模式有三个特点 </p><ul><li>该类只有一个实例 </li><li>该类自行创建该实例(在该类内部创建自身的实例对象) <a id="more"></a></li><li>向整个系统公开这个实例接口 </li></ul><h5 id="Singleton模式的简单实现"><a href="#Singleton模式的简单实现" class="headerlink" title="Singleton模式的简单实现"></a>Singleton模式的简单实现</h5><p>1.最简单的单例实现方法,即将构造方法私有化,在类的内部创建该类的唯一实例,然后提供一个静态方法作为获取该实例的接口,犹如以下代码<br><img src="/images/simple_singleton.png" alt></p><p>2.则该Singleton类的实例可以通过如下这句代码获得 </p><p><img src="/images/simple_singleton_get_code.png" alt></p><p>3.上面的单例实现方式会在Singleton类加载的时候立即初始化一个实例,称为饿汉式加载。但对于资源开销比较大的类,更适合的做法是将实例化推迟到第一次使用它的时候,即懒汉式加载(惰性加载),比如以下代码 </p><p><img src="/images/lazy_singleton.png" alt></p>]]></content>
<categories>
<category> 玩转spring </category>
</categories>
<tags>
<tag> Spring </tag>
</tags>
</entry>
<entry>
<title>一起学java之Java中的反射机制简介</title>
<link href="/2909453862.html"/>
<url>/2909453862.html</url>
<content type="html"><![CDATA[<h4 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h4><p>Reflection,反射,在java中指的是我们可以于运行时加载,探知,使用编译期间完全未知的类,包括实例化对象,唤醒其方法,对其fields设值等 </p><a id="more"></a><h4 id="Class类"><a href="#Class类" class="headerlink" title="Class类"></a>Class类</h4><p>1.在java中,万物皆对象,java中的类是为了描述对象,包括:类名,属性,方法等类结构,java中把类的描述也定义为类,该类比较特殊,名称是Class.每一个类在加载时,虚拟机都会根据加载的类创建对应的Class对象,放在内存的程序区,Class对象是具体类的描述,包括具体类的类名,方法,属性,构造方法等。 </p><p>2.理解Class类 </p><p><img src="/images/20191025150322.png" alt></p><h4 id="Class类的应用"><a href="#Class类的应用" class="headerlink" title="Class类的应用"></a>Class类的应用</h4><p>1.如何加载类 </p><ul><li>在第一次使用类时会加载类,(声明类的变量或new类的对象) </li><li>主动加载(类名.class 或 Class.forName(“类名”)) </li><li>Class对象一旦加载成功,在程序运行结束之前,Class对象永远存储在程序区,直到应用程序结束 </li><li>一个类只加载一次,重复加载则无效 </li><li>举例: </li></ul><p><img src="/images/20191025150425.png" alt></p><p>2.如何得到一个类的Class对象 </p><ul><li>对象名.class </li><li>类名.class </li><li>Class.forName(“类名”) </li><li>举例 </li></ul><p><img src="/images/20191025150540.png" alt></p><p>3.如何获得一个类有哪些属性 </p><table><thead><tr><th>方法名称</th><th>说明</th></tr></thead><tbody><tr><td>Field[] getFields()</td><td>得到类的公共属性</td></tr><tr><td>Field[] getDeclaredFields()</td><td>得到声明的字段</td></tr><tr><td>Field getField(String )</td><td>得到对应的字段,必须是公共的</td></tr><tr><td>…</td><td>…</td></tr></tbody></table><ul><li>举例 </li></ul><p><img src="/images/20191025150822.png" alt></p><p>4.如何获得一个类有哪些方法 </p><ul><li>常用方法 </li></ul><table><thead><tr><th>方法名称</th><th>说明</th></tr></thead><tbody><tr><td>Method[] getMethods()</td><td>得到类的公共方法,包括父类的</td></tr><tr><td>Method[] getDeclaredMethods()</td><td>得到声明的方法,不包括父类的</td></tr><tr><td>Method getMethod(String,…Class )</td><td>得到对应的方法</td></tr><tr><td>…</td><td>…</td></tr></tbody></table><ul><li>举例 </li></ul><p><img src="/images/20191025151107.png" alt></p><p>5.如何产生一个类的对象 </p><ul><li>使用newInstance()方法 </li><li>举例 </li></ul><p><img src="/images/20191025151158.png" alt></p><p>6.如何使用类的属性,赋值和取值 </p><ul><li>举例 </li></ul><p><img src="/images/20191025151250.png" alt></p><p>7.如何使用类的方法,调用方法 </p><ul><li>Invoke()方法 </li><li>举例 </li></ul><p><img src="/images/20191025151351.png" alt></p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之线程简介</title>
<link href="/558031296.html"/>
<url>/558031296.html</url>
<content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><p>至今为止,我们开发的java project在同一时间只能进行一项任务,如果程序运行中遇到了耗时的任务,程序必须等待任务完成之后才能执行后面的代码。这样的单线程结构不能充分的利用计算机的硬件资源,代码运行效率不高,合理的利用多线程结构,可以并行的处理多项任务,避免了不相关任务之间的等待,充分利用硬件资源提高程序的效率 </p><a id="more"></a><h4 id="什么是线程"><a href="#什么是线程" class="headerlink" title="什么是线程"></a>什么是线程</h4><p>1.程序:写好的代码,不一定运行 </p><p>2.进程:运行起来的程序就叫进程 </p><p><img src="/images/20191024111427.png" alt></p><p>3.线程:一个进程中可能包含多端程序并发执行,每一段独立的正在执行的程序称之为线程。也就是说,一个进程由若干个线程组成,main函数启动进程,那么该线程称之为主线程。 </p><p>4.通常情况下,只有子线程运行结束,主线程才会结束,主线程结束,那么进程也就结束了,特殊情况下,主线程结束,子线程随之马上结束,那么该子线程称为守护线程。 </p><p>5.多个线程之间可以并发执行,也可以根据需要让一个线程等待另一个线程,或暂停一个线程。一般来说,线程的状态有就绪(new)、执行(runnable)、等待(waiting)、阻塞(blocked)、终止(terminated)等。 </p><h4 id="线程实现"><a href="#线程实现" class="headerlink" title="线程实现"></a>线程实现</h4><p>1.线程实现,需要创建线程对象。线程实现主要有两种方法 </p><ul><li><p>实现Runnable接口 </p><ul><li><p>举例 </p><p><img src="/images/20191024111615.png" alt></p></li></ul></li><li><p>继承Thread类 </p><ul><li><p>举例 </p><p><img src="/images/20191024111706.png" alt></p></li></ul></li></ul><p>2.应用实例-多线程文件拷贝 </p><ul><li>用来拷贝的类FileCopyThread </li></ul><p><img src="/images/20191024111832.png" alt></p><ul><li>main方法测试 </li></ul><p><img src="/images/20191024111924.png" alt></p><ul><li>说明: <ul><li>线程必须覆盖父类的run方法,run方法中的代码会在线程启动的时候执行的时候执行,run方法执行结束,线程也就执行结束,变为终止状态。 </li><li>实例化线程会使线程处于就绪状态,但这时不会执行线程中的代码 </li><li>调用线程的start方法会启动线程,将线程变为执行状态 </li><li>在硬件资源允许的情况下,使用多线程并行复制要比单线程逐个复制快很多 </li></ul></li></ul><h4 id="线程等待"><a href="#线程等待" class="headerlink" title="线程等待"></a>线程等待</h4><p>1.使用Thread.sleep(),可以让当前线程等待一段时间 </p><p>2.使用TimeUnit.SECONDS.sleep(),可以让当前线程等待一段时间,其中的SECONDS 表示的是秒,还可以是分钟,小时,天等 </p><h4 id="守护线程"><a href="#守护线程" class="headerlink" title="守护线程"></a>守护线程</h4><p>1.除了希望并行执行的代码会使用线程,一些不间断的监视工作也会用到线程 </p><p>2.java垃圾回收线程即是一个守护线程 </p><p>3.举例 </p><ul><li>实现监视磁盘空间的Thread类 </li></ul><p><img src="/images/20191024112241.png" alt></p><ul><li>main方法测试 </li></ul><p><img src="/images/20191024112322.png" alt></p><ul><li>说明 <ul><li>执行thread.setDaemon(true)可以将线程标记为守护线程 </li><li>在所有非守护线程结束后,程序就会终止执行 </li><li>一旦线程已经启动,就不能调用setDaemon()方法了 </li></ul></li></ul><h4 id="线程安全"><a href="#线程安全" class="headerlink" title="线程安全"></a>线程安全</h4><p>1.B/S架构软件开发模式会经常遇到多线程并行访问的问题,一段代码如果在多线程并行访问的情况下依然能够得到预期的结果,称之为线程安全,否则为非线程安全 </p><p>2.非线程安全的例子 </p><p><img src="/images/20191024112425.png" alt></p><p>3.解决办法 </p><ul><li>加锁 </li></ul><p><img src="/images/20191024112528.png" alt></p><ul><li>加同步块 </li></ul><p><img src="/images/20191024112552.png" alt></p><ul><li>说明 <ul><li>一般认为,如果一段代码可能被多个线程访问,这段代码又会访问诸如堆内存中的对象,数据库中的数据,磁盘上的文件等公共资源时需要加锁,如果只需要访问栈内存中的数据,不需要加锁。 </li></ul></li></ul>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之I/O简介</title>
<link href="/1725226475.html"/>
<url>/1725226475.html</url>
<content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><p>Java的核心库java.io提供了全面的IO接口。包括:文件读写、标准设备输出等。Java中IO是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。</p><a id="more"></a><h4 id="File文件操作"><a href="#File文件操作" class="headerlink" title="File文件操作"></a>File文件操作</h4><p>1.Java如何描述文件系统:File类 </p><p>2.File类中常用的方法: </p><p><img src="/images/20191017095307.png" alt></p><p>3.方法举例 </p><p><img src="/images/20191017095417.png" alt></p><p><img src="/images/20191017095449.png" alt></p><h4 id="IO流结构"><a href="#IO流结构" class="headerlink" title="IO流结构"></a>IO流结构</h4><p>1.IO流的用途,进行文件等的读写操作 </p><p>2.IO流的概念:流可以理解为连续的数据 </p><p>3.IO流的分类: </p><ul><li>输入流和输出流 </li><li>文件操作流和内存操作流等 </li><li>字节操作流和字符操作流等 </li></ul><p>4.结构图 </p><p><img src="/images/20191017095707.png" alt></p><p>5.一般来说,IO流的后缀有InputStream,OutputStream,Reader,Writer四种,分别代表字节输入流,字节输出流,字符输入流,字符输出流,前缀则代表了流的操作对象 </p><p>6.在对文件的读写操作中,字节流可以读写二进制文件,字符流用来读写文本文件. </p><ul><li>所谓二进制文件,指文件无字符编码格式,均由字节(Byte)组成,图片文件,word文档等均为二进制文件 </li><li>文本文件,是一种特殊的二进制文件,也由字符组成,但需要通过特定的字符编码格式读取或写入,否则会出现乱码,可以用记事本打开的文件都是文本文件 </li></ul><h4 id="使用字节流读取文件"><a href="#使用字节流读取文件" class="headerlink" title="使用字节流读取文件"></a>使用字节流读取文件</h4><p>1.使用FileInputStream </p><ul><li><p>步骤: </p><ul><li>打开文件 </li><li>按字节流读取文件 </li><li>关闭文件 </li></ul></li><li><p>举例 </p><ul><li><p>例1 </p><p><img src="/images/20191023135454.png" alt></p></li><li><p>注意: </p><ul><li>read方法返回一个-1到255之间的一个整数,即一个字节,如果返回-1说明读到了文件尾 </li><li>如果1.txt中为英文,可以在控制台显示,如果1.txt中有中文的话,控制台就会出现乱码,可见字节流在读取文本文件时的不足 </li></ul></li><li><p>例2 </p><p><img src="/images/20191023135647.png" alt></p><ul><li>注意:FileInputStream效率较低,BufferedInputStream效率较高 </li></ul></li></ul></li></ul><h4 id="使用字节流写文件"><a href="#使用字节流写文件" class="headerlink" title="使用字节流写文件"></a>使用字节流写文件</h4><p>1.使用OutputStream </p><ul><li><p>步骤:开发文件,输出,关闭文件 </p></li><li><p>举例 </p><ul><li><p>例1 </p><p><img src="/images/20191023135928.png" alt></p><ul><li>注意:写入的是ASCII码值,文件不存在时会自动创建文件 </li></ul></li><li><p>例2 </p><p><img src="/images/20191023140023.png" alt></p><ul><li>注意:FileOutputStream也存在性能问题,可以和BufferedOutputStream配合使用 </li></ul></li></ul></li></ul><h4 id="文件拷贝"><a href="#文件拷贝" class="headerlink" title="文件拷贝"></a>文件拷贝</h4><p>1.举例: </p><p><img src="/images/20191023140128.png" alt></p><h4 id="使用字符流读写文件"><a href="#使用字符流读写文件" class="headerlink" title="使用字符流读写文件"></a>使用字符流读写文件</h4><p>1.字符流的操作方法和字节流基本相同,字符流会根据当前的操作系统与语言环境选择适当的字符编码格式读写文件,适合读取文本文件,因为字符流会对文件内容进行编码,所以不适合用于读取二进制文件. </p><p>2.举例 </p><ul><li>例1 </li></ul><p><img src="/images/20191023140233.png" alt></p><p>例2 </p><p><img src="/images/20191023140306.png" alt></p><ul><li>注意:BufferedWriter提供了输出整行字符串的方法,需注意换行时使用newLine方法,而不是输出一个”\n” </li></ul><h4 id="使用其他常用流"><a href="#使用其他常用流" class="headerlink" title="使用其他常用流"></a>使用其他常用流</h4><p>1.对象输入输出流,ObjectInputStream和ObjectOutputStream能够针对对象进行读写操作 </p><ul><li>举例: </li></ul><p><img src="/images/20191023140410.png" alt></p><p><img src="/images/20191023140445.png" alt></p><ul><li>注意: <ul><li>类必须实现java.io.Serializable接口才能将实例转换为流操作 </li><li>通过writeObject方法可以将实现了序列化接口的类实例写入流中 </li><li>通过readObject方法可以从流中将实现了序列化接口的类实例读取出来 </li></ul></li></ul><p>2.字节输入输出流:InputStreamReader和OutputStreamReader能够通过制定的编码格式将字节流转换为字符流,并进行读写操作 </p><ul><li>举例: </li></ul><p><img src="/images/20191023140540.png" alt></p><h4 id="Properties类应用"><a href="#Properties类应用" class="headerlink" title="Properties类应用"></a>Properties类应用</h4><p>1.Properties是什么? </p><ul><li>java提供了Properties类简化配置文件的读写操作,Properties与HashMap相似,属于Map集合,适合读写键值对形式的配置文件 </li><li>Properties中提供了load和store两个方法,方便从文件中读写集合的内容 </li></ul><p>举例: </p><p><img src="/images/20191023140651.png" alt></p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之异常简介</title>
<link href="/1929845495.html"/>
<url>/1929845495.html</url>
<content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><p>程序运行中不可能一帆风顺,就算代码没有问题,也不能保证用户总是按程序员的意思输入,不能保证操作系统永远正常运转,网络永远通畅,如果程序中出现问题,不及时处理,程序会挂起会自动退出,程序的健壮性会大大降低 </p><a id="more"></a><h4 id="try-catch-finally"><a href="#try-catch-finally" class="headerlink" title="try_catch_finally"></a>try_catch_finally</h4><p>1.我们已经见过的异常:两数相除,除数是0;数组越界;数字格式异常,空指针等等 </p><ul><li>举例: </li></ul><p><img src="/images/20191016155011.png" alt></p><ul><li>语法 </li></ul><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">try{ </span><br><span class="line"></span><br><span class="line">//正常程序 </span><br><span class="line"></span><br><span class="line">}catch(异常类型 异常对象){ </span><br><span class="line"></span><br><span class="line">//异常处理 </span><br><span class="line"></span><br><span class="line">}finally{ </span><br><span class="line"></span><br><span class="line">//最后执行 </span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li><p>说明: </p><ul><li>java中把可能出现异常的地方用try监控起来,如果程序运行中,try块中出现异常,则终止try块中其他语句的执行,转到catch块中执行相应的异常处理,如果try块执行正常,则不执行catch块中的语句 </li><li>finally块中可以省略,如果有finally块中的语句,不管有没有异常,都会执行 </li><li>java中追求万物皆对象,当然我们抓到的异常其实是封装了具体异常信息的一个对象 </li></ul></li><li><p>举例: </p></li></ul><p><img src="/images/20191016155130.png" alt></p><ul><li>注意:<ul><li>多重catch,当一段代码中可能有多种异常时,可以在同一个try块后使用多重catch,需要注意的是,父类异常应该尽量放在后面,否则子类异常就捕获不到了 </li></ul></li></ul><h4 id="java中的异常"><a href="#java中的异常" class="headerlink" title="java中的异常"></a>java中的异常</h4><p>1.java中常见的异常可以在API文档中查到 </p><p>2.java中的异常 </p><p><img src="/images/20191016155344.png" alt></p><p>3.说明: </p><ul><li>Throwable继承自Object,Error和Exception类用于处理java中的异常,Throwable,Error,Exception类的实例和他们子类的实例都被JVM识别为异常对象 </li><li>Error和Error的子类被识别为致命的,程序无法修复的错误,很罕见,如VirtualMachineError,这类问题一般不希望用户的程序捕获他们,因此,一般不处理Error问题 </li><li>Exception类型的异常被认识为可控制的异常,可以在程序中捕获处理,其子类RuntimeException称为运行时异常,该类异常通过程序员的努力,基本上可以避免 </li><li>另外是非运行时异常,要求程序中必须用try_catch包围,程序在编译时就会检查是否对该类异常进行了处理,如果程序没有捕获非运行时异常,将无法通过编译 </li></ul><p>4.常见的异常 </p><p><img src="/images/20191016155448.png" alt></p><p>5.异常类的方法 </p><ul><li>java中的异常信息主要调用Throwable的几个方法进行处理,主要的方法有: <ul><li>printStackTrace():输出异常详细信息,包括异常原因,发生位置等 </li><li>getMessage():返回异常详细信息,但是无法跟踪到行 </li><li>说明:还有其他的一些方法,可以查阅API文档哦~~ </li></ul></li></ul><h4 id="自定义异常"><a href="#自定义异常" class="headerlink" title="自定义异常"></a>自定义异常</h4><p>1.系统定义的异常不能代表程序中所有的异常,有时需要自定义异常 </p><p>2.自定义异常通常是可控的,只要继承RuntimeException类就可以了 </p><h4 id="throw和throws"><a href="#throw和throws" class="headerlink" title="throw和throws"></a>throw和throws</h4><p>1.使用throw抛出异常 </p><p>2.异常捕获或者throws抛出异常给调用者 </p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之面向对象的编程2</title>
<link href="/3922073342.html"/>
<url>/3922073342.html</url>
<content type="html"><![CDATA[<h4 id="final关键字"><a href="#final关键字" class="headerlink" title="final关键字"></a>final关键字</h4><p>1.<code>final</code>:最终的,<code>final</code>关键字在<code>java</code>中可以修饰类,成员方法,成员变量和局部变量 </p><p>2.<code>final</code>修饰的类,表示”最终的类”,该类不能被继承,以前使用过的<code>String</code>类,<code>System</code>类,<code>java.util.Scanner</code>类都是被<code>final</code>修饰的 </p><a id="more"></a><ul><li>语法: </li></ul><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">public final class 类名{...}</span><br></pre></td></tr></table></figure><ul><li>举例: </li></ul><p><img src="/images/20191014110424.png" alt></p><p>3.<code>final</code>修饰的方法,不能在子类中重写 </p><ul><li>语法: </li></ul><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">public final 返回值类型 方法名 ([参数列表]){...}</span><br></pre></td></tr></table></figure><ul><li>举例: </li></ul><p><img src="/images/20191014110553.png" alt></p><p>4.<code>final</code>修饰的变量,其值将不能重新赋值,即称为常量 </p><ul><li>语法: </li></ul><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">public static final 变量类型 变量名 = 初始值;</span><br></pre></td></tr></table></figure><ul><li>举例: </li></ul><p><img src="/images/20191014110712.png" alt></p><ul><li>注意,<code>java</code>中的常量一般由<code>static final</code>同时修饰,常量的命名一般使用大写字母,多个单词之间用下划线分割 </li></ul><h4 id="抽象类"><a href="#抽象类" class="headerlink" title="抽象类"></a>抽象类</h4><p>1.抽象类是使用<code>abstract</code>修饰的类,包含没有方法实现的抽象方法,抽象方法也用<code>abstract</code>修饰 </p><ul><li><p>举例: </p><ul><li><p>抽象的Pet类,有抽象的shout方法 </p><p><img src="/images/20191014111312.png" alt></p></li><li><p>继承Pet类的Cat类和Dog类,实现了shout方法</p><p><img src="/images/20191014111411.png" alt></p></li><li><p>运行结果: </p><p><img src="/images/20191014111459.png" alt></p></li></ul></li></ul><p>2.抽象类是为了实现多态,并优化继承结构的 </p><p>3.抽象类可能只提供了一个类的部分实现,因此abstract类不能实例化 </p><p>4.抽象类可以有成员变量,可以有一个或多个构造方法,但是这些构造方法不能被客户端调用来创建实例,抽象类的构造方法可以被其子类用super来调用 </p><p>5.原则: </p><ul><li>尽可能的不要从具体类继承 </li><li>抽象类拥有尽可能多的共同代码,以提高代码的重用率 </li></ul><h4 id="接口"><a href="#接口" class="headerlink" title="接口"></a>接口</h4><p>1.接口在现实生活中经常遇到,比如:电线插座和插头,螺丝帽的规格,电脑主板上的各种插槽等。接口就是规定了一系列的规格,标准,动作等,不做具体实现。 </p><p>2.接口用interface来声明。一个类中如果不存在数据,只存在抽象方法时,就可以声明为接口。 </p><ul><li>接口声明举例: </li></ul><p><img src="/images/20191014111928.png" alt></p><ul><li>用interface关键字声明接口。接口中的方法不能实现,接口中方法的默认修饰符是public abstract。 </li></ul><p>3.接口与类是并列的概念,类可以被继承,接口只能被实现,实现接口是用关键字implements,一个类同时可以实现多个类中的方法,实现多个接口时,接口之间用逗号分隔。 </p><ul><li>接口实现举例: </li></ul><p><img src="/images/20191014112109.png" alt> </p><ul><li>接口实现用implements关键字,类Cat实现了Pet接口,默认继承了Object类。接口中的所用方法必须全部实现,如果只是部分实现,该类就是抽象类。 </li></ul><p>4.抽象类和接口的比较 </p><ul><li>abstract class在java语言中表示的一种继承关系,一个类只能使用一次继承关系,但是一个类可以实现多个interface。 </li><li>在abstract class中可以有自己的数据成员,非abstract的成员方法和abstract方法,而在interface中,只能够有静态的不能被修改的数据成员(也就必须是static final的,即常量),所有的成员方法必须都是public abstract的。 </li><li>实现抽象类和接口的类必须实现其中的所有抽象方法,抽象类中可以有非抽象的方法(即实现了的方法),而接口中不能有方法实现。 </li><li>一般情况下,在使用继承的时候,优先考虑定义接口,其次考虑定义抽象类。 </li></ul><h4 id="枚举"><a href="#枚举" class="headerlink" title="枚举"></a>枚举</h4><p>1.Jdk1.5以后,java引进了一个全新的关键字enum来定义一个枚举类。 </p><p>2.枚举适用于一些数据具有若干特定值得场合,使用方法如同一个类 </p><ul><li>枚举定义举例 </li></ul><p><img src="/images/20191014113322.png" alt></p><ul><li>枚举使用举例 </li></ul><p><img src="/images/20191014113442.png" alt></p><h4 id="内部类"><a href="#内部类" class="headerlink" title="内部类"></a>内部类</h4><p>1.定义在一个public类内部的类即是内部类,出于对一些类使用权限,数据安全,代码隐藏方面的考虑。 </p><p>2.内部类可以分为成员内部类,局部内部类,嵌套内部类,匿名内部类等 </p><ul><li>内部类的使用举例1 </li></ul><p><img src="/images/20191014113551.png" alt></p><ul><li>内部类Bird,可以定义在Boy内部,定义在内部时,外部访问受到限制,有利于数据安全和代码隐蔽。内部类可以被static修饰,也可以被public修饰,但一般情况下内部类不使用public修饰,目的是为了内部类的安全性考虑。内部类可以像外部类一样使用。 </li></ul><ul><li>内部类的使用举例2(匿名内部类) </li></ul><p><img src="/images/20191014113655.png" alt></p><ul><li>在程序设计中,如果接口或者抽象类中需要实现的方法很少,临时使用接口或抽象类时,重新定义一个类单独实现方法又有些麻烦,可以直接使用匿名内部类对接口或者抽象类进行实现。 </li><li>在匿名内部类中访问局部变量name,要求局部变量必须是final变量。 </li></ul><p>3.内部类降低了代码重用性,增加了代码的阅读难度 </p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之集合框架</title>
<link href="/8847.html"/>
<url>/8847.html</url>
<content type="html"><![CDATA[<h4 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h4><p>1.数组长度一旦确定,就无法更改,除非建立新的数组,比较浪费内存,操作不方便,java为我们提供了许多容器类 </p><p>2.容器各有特点,使用时视情况而定 </p><a id="more"></a><p><img src="/images/20191014102800.png" alt></p><h4 id="List"><a href="#List" class="headerlink" title="List"></a>List</h4><p>1.List集合与数组的用途非常相似,但又有同 </p><ul><li>数组长途在使用前必须确定,一旦确定不能改变,而List集合长度可变,无需定义 </li><li>数组中必须存放同一类型的数据,Lise集合中可以存放不同数据类型的数据 </li><li>常用的的List集合有ArrayList,LinkedList和Vector,功能与用法基本相同,但内部实现不同 </li><li>List集合已经重写了toString方法,可以将集合中的元素依次输出 </li><li>插入情况多 就用LinkedList,随机访问多就是ArrayList<ul><li>在插入的情况下LinkedList先是在双向链表中找到要插入节点的位置index;找到之后,再插入一个新节点。</li><li>ArrayList是基于数组,每次插入的时候都要调用System.arraycopy,该方法会导致重新计算索引 故而插入慢, </li><li>在随机访问时 ArrayList只要拿到下标就能拿到元素 ,LinkedList需要查找这个元素所在的位置 </li></ul></li></ul><p>2.List集合中的常用方法 </p><p><img src="/images/20191014103307.png" alt></p><p>3.使用contains等方法时,应该重写类的equals方法,因为这些方法要调用equals方法类比较两个对象是否相等 </p><ul><li>Student类中重写了eauqls方法: </li></ul><p><img src="/images/20191014103410.png" alt></p><ul><li>进行比较的结果: </li></ul><p><img src="/images/20191014103455.png" alt></p><p>4.ArrayList,LinkedList和Vector的区别 </p><ul><li>Vector为线程安全的,ArrayList和LinkedList非线程安全,Vector性能稍微逊色 </li><li>ArrayList用数组实现,添加大量数据,插入数据等时,效率稍微逊色,但按下标查找时效率很高 </li><li>LinkedList使用链表实现,添加,插入,删除元素时只需对相邻元素进行调整即可,效率很高,但按下标查找时效率较低 </li><li>一般来说,ArrayList保存经常用来查询的数据,LinkedList适用于保存经常进行修改操作的集合 </li></ul><h4 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h4><p>1.Set集合与List集合的很多用法是相同的,但Set集合中的元素是无序的,唯一的,常用的Set集合为HashSet </p><p>2.常用方法,与List基本相同,不再赘述 </p><p>3.Set集合的迭代 </p><ul><li>使用Set的iterator()方法类获取迭代器对象,迭代器是Iterator类的实例 </li><li>使用迭代器的hasNext()方法判断集合中是否还有元素,配合while循环来迭代 </li><li>使用迭代器的next()方法取得集合中的元素 </li></ul><p><img src="/images/20191014103722.png" alt></p><p>4.Set存储基本类型(自动装箱成包装类)和字符串时是不会重复的,但存储我们自定义的类的对象时会出现重复的数据,是因为Set根据hashCode来判断存储位置,如果hashCode 相同,再根据equals方法比较,但我们在没有重写hashCode方法时,对象在内存中的地址不同,会返回不同的hashCode,故会出现两个对象数据一样,但由于hashCode不同而被重复记录在Set中的情况,此时,我们需要重写hashCode方法,使数据相同的对象返回相同的hashCode. </p><ul><li>重写hashCode方法: </li></ul><p><img src="/images/20191014103915.png" alt></p><ul><li>运行结果: </li></ul><p><img src="/images/20191014104008.png" alt></p><ul><li>在编写java程序中,hashCode和equals这两个方法有这样的规律: <ul><li>hashCode()方法返回值相同时,equals()方法比较不一定相等 </li><li>equals()方法比较相等时,hashCode方法返回值是相同的 </li></ul></li></ul><h4 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h4><p>1.通过List集合存储元素之后,如果想获取某一个特点的对象,操作比较繁琐,需要遍历List,此时我们可以使用Map </p><p>2.Map以键值对的形式存储数据(key–>value) </p><p><img src="/images/20191014104132.png" alt></p><p>3.常用的Map集合为HashMap和Hashtable </p><ul><li>HashMap的常用方法 </li></ul><p><img src="/images/20191014104229.png" alt></p><ul><li>Map集合中key的维护是依靠Set集合,故key不能重复,添加key相同的映射关系时,后面添加的映射关系会覆盖前面的映射关系 </li><li>HashMap和Hashtable的主要区别: <ul><li>Hashtable是线程安全的,HashMap是非线程安全的,HashMap比Hashtable的性能更高 </li><li>Hashtable不允许使用null值作为key或value,但是HashMap是可以的 </li></ul></li></ul><p>举例: </p><p><img src="/images/20191014104333.png" alt></p><h4 id="Collections工具类"><a href="#Collections工具类" class="headerlink" title="Collections工具类"></a>Collections工具类</h4><p>1.Collections类与Arrays类一样都提供了一系列静态方法,只是Arrays主要操作数组,而Collections主要操作List集合,同时还有对Set的相关操作 </p><p>2.Collections类提供了一系列的静态方法,可以使用类名.方法名直接调用 </p><ul><li>常用方法</li></ul><p><img src="/images/20191014104444.png" alt></p><ul><li>在List中查找一个对象时,该对象必须实现Comparable接口 </li></ul><p><img src="/images/20191014104641.png" alt></p><h4 id="泛型-Generic"><a href="#泛型-Generic" class="headerlink" title="泛型(Generic)"></a>泛型(Generic)</h4><p>1.集合中要求装入的是Object类型的对象,故在拿到对象使用的时候要强制类型转换 </p><p>2.泛型可以使集合在实例化时就规定好将来要装入什么类型的对象,从集合中取出元素时,不再需要强制类型转换 </p><ul><li>举例: </li></ul><p><img src="/images/20191014104815.png" alt></p><p>3.自定义的类也可以使用泛型 </p><ul><li>举例: </li></ul><p><img src="/images/20191014104859.png" alt></p><ul><li>结果: </li></ul><p><img src="/images/20191014104933.png" alt> </p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之jdk常用工具类</title>
<link href="/55382.html"/>
<url>/55382.html</url>
<content type="html"><![CDATA[<h5 id="Date"><a href="#Date" class="headerlink" title="Date"></a>Date</h5><p>1.Data类位于java.util包中,表示时间 </p><p>2.Date该类包装了一个毫秒值,表示从1970年1月1日00:00:00 GMT开始到现在毫秒数 </p><a id="more"></a><p>3.Date类的两个常用构造方法 </p><ul><li>Date(),按照当前系统时间创建一个Date对象 </li><li>Date(long date),按照给定的时间毫秒值创建一个Date对象 </li></ul><p><img src="/images/20191011134515.png" alt></p><p>4.主要的方法 </p><p><img src="/images/20191011134700.png" alt></p><p>举例: </p><p><img src="/images/20191011134827.png" alt></p><h5 id="SimpleDateFormat"><a href="#SimpleDateFormat" class="headerlink" title="SimpleDateFormat"></a>SimpleDateFormat</h5><p>1.使用SimpleDateFormat类来格式化时间,使之成为自己想要的格式 </p><ul><li>举例: </li></ul><p><img src="/images/20191011135236.png" alt></p><ul><li>说明:yyyy表示年,MM表示月,dd表示日,HH表示24小时制的小时数,hh表示12小时制的小时数,mm表示分钟,ss表示秒 </li></ul><p>2.如何将字符串对象转换成Date对象? </p><ul><li>使用SimpleDateFormat的parse()方法 </li><li>举例: </li></ul><p><img src="/images/20191011135147.png" alt></p><h5 id="NumberFormat"><a href="#NumberFormat" class="headerlink" title="NumberFormat"></a>NumberFormat</h5><p>1.数字格式化也是在程序中常用的技巧,主要是对小数位数,表示形式等的格式化<br>2.NumberFormat使用getInstance()方法实例化<br>3.可以使用NumberFormat进行数字格式化 </p><p><img src="/images/20191011135454.png" alt></p><p>4.也可以使用Decimalformat进行数字格式化 </p><p><img src="/images/20191011135544.png" alt></p><ul><li>注意: <ul><li>#:代表一个位置数字,如果该位置数字不存在,则不显示 </li><li>,:代表数字中的分割符 </li><li>0:代表一个数字位置,如果该位置不存在,则用0来补充,小数中多余的部分四舍五入 </li><li>.:代表小数点 </li><li>E:科学计数法 </li><li>%:用百分号表示数字 </li></ul></li></ul><h5 id="Calendar"><a href="#Calendar" class="headerlink" title="Calendar"></a>Calendar</h5><p>1.用来记录日期的日历类Calendar </p><p>2.使用getInstance()方法实例化 </p><p>3.常用方法: </p><p><img src="/images/20191011135750.png" alt></p><ul><li>使用时请注意星期,月份等与实际值之间的差异 </li></ul><p>4.Calendar与Date的转换 </p><ul><li>Calendar转化为Date </li></ul><figure class="highlight plain hljs"><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">Calendar cal=Calendar.getInstance(); </span><br><span class="line"></span><br><span class="line">Date date=cal.getTime();</span><br></pre></td></tr></table></figure><ul><li>Date转化为Calendar </li></ul><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">Date date=new Date(); </span><br><span class="line"></span><br><span class="line">Calendar cal=Calendar.getInstance(); </span><br><span class="line"></span><br><span class="line">cal.setTime(date);</span><br></pre></td></tr></table></figure><h5 id="Math"><a href="#Math" class="headerlink" title="Math"></a>Math</h5><p>1.java.lang.Math类包含了许多常用数学运算,全部为静态方法 </p><p>2.方法举例: </p><p><img src="/images/20191011135953.png" alt></p><p>3.两个常用的常量,Math.E和Math.PI分别表示自然对数的底数和圆周率 </p><p><img src="/images/20191011140052.png" alt></p><p>4.还有其他方法,使用时勤查API文档即可 </p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之面向对象编程1</title>
<link href="/24774.html"/>
<url>/24774.html</url>
<content type="html"><![CDATA[<h5 id="static修饰符"><a href="#static修饰符" class="headerlink" title="static修饰符"></a>static修饰符</h5><p>1.static,静态 </p><ul><li>在java中,static用来修饰类的成员变量,方法等 </li><li>static修饰类的成员变量,称为类的静态变量,static修饰类的方法,称为静态方法 <a id="more"></a></li><li>在程序运行时,第一次加载类的时候,初始化静态变量,静态变量会一直到应用程序结束才被系统销毁 </li><li>静态变量不依赖类的某一个实例,所有的实例共享同一份静态变量 </li><li>静态方法也不依赖类的某一个实例 </li></ul><p><img src="/images/2019101104744.png" alt></p><p>2.静态变量和静态方法的调用 </p><ul><li>语法: </li></ul><figure class="highlight plain hljs"><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><br><span class="line"></span><br><span class="line">类名.静态方法名();</span><br></pre></td></tr></table></figure><ul><li>由于静态变量被所有的对象共有,因此在一个对象中改变静态变量,其他的对象中也会看到变化 </li><li>举例: </li></ul><p><img src="/images/20191011105018.png" alt></p><p>3.比较静态变量和成员变量 </p><p><img src="/images/20191011105515.png" alt></p><p>4.比较静态方法和普通方法 </p><p><img src="/images/20191011105617.png" alt></p><p>5.静态代码块 </p><ul><li>静态代码块可以使类在第一次加载后进行一些操作,一般情况下用来初始化静态变量 </li><li>语法 </li></ul><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">static{ </span><br><span class="line"></span><br><span class="line">//语句块 </span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="Object-Oriented"><a href="#Object-Oriented" class="headerlink" title="Object Oriented"></a>Object Oriented</h5><ul><li>OO:Object Oriented,面向对象 </li><li>OOA:Object Oriented Analysis,面向对象的分析 </li><li>OOD:Object Oriented Design,面向对象设计 </li><li>OOP:Object Oriented Programming,面向对象的编程 <ul><li>面向对象最大的特点是,程序研发人员可以根据具体的问题,设计出任何需要的类,用来解决问题.面向对象是一种思想!!! </li></ul></li></ul><h5 id="封装"><a href="#封装" class="headerlink" title="封装"></a>封装</h5><p>1.封装将对象的属性和方法结合在一起,统一提供对外的访问权限,分装可以将类的使用者和设计者分开,设计者可以决定哪些内容可以提供给使用者,使用者在使用的时候不需要了解设计者是如何实现的 </p><p><img src="/images/20191011110015.png" alt></p><p>2.在java中,类把数据和方法封装到一起,对数据和方法操作起到一种保护作用. </p><p>3.用public,private,protected来控制对属性和方法的访问 </p><p>4.控制权限的修饰符 </p><ul><li>public <ul><li>即公开的,用public修饰的属性和方法,其他任何类都可以访问 </li></ul></li><li>private <ul><li>即私有的,用private修饰的属性和方法,其他任何类都不能访问,只有在当前类内部才可以访问 </li></ul></li><li>protected <ul><li>即表示受保护的,用protected修饰的属性和方法,允许相同包中的其他类(包括子类)或非相同包的子类访问 </li></ul></li><li>缺省修饰符 <ul><li>缺省修饰符的属性和方法允许相同包中的其他类进行访问,不允许其他包中的类(包括子类)访问 </li></ul></li></ul><p>5.一般情况下,属性用private修饰,并为private修饰的属性提供一组get/set方法(属性访问器). </p><p><img src="/images/20191011110335.png" alt></p><p>6.public修饰符还可以用来修饰类,可以用来修饰类的修饰符如下: </p><p><img src="/images/20191011110456.png" alt></p><h5 id="方法重载-Overload"><a href="#方法重载-Overload" class="headerlink" title="方法重载(Overload)"></a>方法重载(Overload)</h5><p>1.System.out.println()方法是重载过的 </p><p>2.在同一个类中,一个方法名称可以定义多个方法,只要方法参数列表不同即可,这叫做方法的重载 </p><p><img src="/images/20191011111847.png" alt></p><p>3.方法重载要求方法名相同,方法参数列表不同,方法的参数列表不同包括 </p><ul><li>方法参数的数量不同 </li><li>方法参数的类型不同 </li><li>相同数量参数中,不同参数类型在方法参数列表中的顺序不同 </li></ul><h5 id="继承-extends"><a href="#继承-extends" class="headerlink" title="继承(extends)"></a>继承(extends)</h5><p>1.事物之间可能存在包含与被包含的关系,程序中设计出的类也会有这种关系.java中使用继承机制描述这一关系,被继承的类称为父类,继承父类的类,称为子类.继承可以减少代码量,方便维护,使程序更符合实际,更符合人的思维习惯 </p><p>2.java中继承使用extends关键字实现,子类继承父类的属性和方法(构造方法除外), </p><p>3.构造方法不能继承,因此继承的子类在默认情况下只有一个无参构造方法 </p><p>4.在java继承中,子类可以访问父类的public,protected修饰的属性和方法,不能访问父类中private修饰的属性和方法;如果子类与父类不在同一个包中声明,那么父类中使用缺省修饰符的属性和方法在子类中也不能被访问. </p><ul><li>权限修饰符总结 </li></ul><p><img src="/images/20191011110832.png" alt></p><ul><li>总结: <ul><li>propected,在同包和子类中访问 </li><li>default,在同包中访问 </li></ul></li></ul><p>5.子类继承后可以重写父类的方法(Override),方法重写必须满足如下要求 </p><ul><li>重写方法和被重写方法必须具有相同的方法名 </li><li>重写方法和被重写方法必须具有相同的参数列表 </li><li>重写方法的返回值类型必须和被重写方法的返回值类型相同或者是其子类 </li><li>重写方法的不能缩小被重写方法的访问权限 </li></ul><p>6.在new子类对象时,首先会调用父类默认无参的构造方法,再调用子类的构造方法,但可以通过super关键字,指定使用父类的某一个构造方法,但super要出现在构造方法的最前面,否则报错. </p><ul><li>super关键字,指向父类对象 </li></ul><p>7.Object类 </p><ul><li>java中,Object类是所有类的父类,所有类默认继承Object类,都具有Object类的方法和属性 </li><li>Object类能够被外界访问的,常用的方法有: </li></ul><p><img src="/images/20191011111129.png" alt></p><ul><li><p>关于toString方法 </p><ul><li>System.out.println()方法可以传入任何参数,包括基本类型和引用类型 </li><li>当用System.out.println()输出一个对象时,首先调用该对象的toString()方法 </li><li>Object类的toString()方法默认输出对象的内存地址 </li><li>经常在类中重写toString()方法. </li></ul></li><li><p>关于equals()方法 </p><ul><li>equals()方法默认比较两个对象的地址 </li><li>如需比较两个对象的内容,需要重写该方法,实际应用中,经常需要重写该方法 </li><li>String类已经重写了该方法 </li></ul></li></ul><h5 id="多态-polymorphic"><a href="#多态-polymorphic" class="headerlink" title="多态(polymorphic)"></a>多态(polymorphic)</h5><p>1.多态:同一种事物,同一种方法,由于条件或环境不同,产生的结果也不同 </p><p>2.方法重载即是多态,称为设计时多态 </p><p>3.在java中,把子类的对像赋值给父类,用父类的引用调用方法的时候,具体执行方法的是子类的对象,也是一种多态形式,称为运行时多态 </p><ul><li><p>举例: </p><ul><li><p>Shape类,有计算面积的area()方法 </p><p><img src="/images/20191011111432.png" alt></p></li><li><p>Circle类,继承Shape,重写area()方法 </p><p><img src="/images/20191011111533.png" alt></p></li><li><p>Square类,继承Shape,重写area()方法 </p><p><img src="/images/20191011111635.png" alt></p></li><li><p>结果 </p><p><img src="/images/20191011111715.png" alt></p></li></ul></li></ul>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之方法</title>
<link href="/1067981242.html"/>
<url>/1067981242.html</url>
<content type="html"><![CDATA[<h6 id="为何要使用方法"><a href="#为何要使用方法" class="headerlink" title="为何要使用方法"></a>为何要使用方法</h6><p>1.事物都是由自身的属性和行为构成的,对象所能完成的行为,即方法. </p><p>2.将相同的操作定义为方法,可以方便代码重用,方便程序的扩展 </p><a id="more"></a><p>3.调用方法的时候,不需要知道方法内部的具体实现,便于封装 </p><h5 id="方法的定义和使用"><a href="#方法的定义和使用" class="headerlink" title="方法的定义和使用"></a>方法的定义和使用</h5><p>1.程序设计中,方法是为了完成某一独立操作的若干条语句的组合. </p><p>2.方法的定义 </p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><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></pre></td></tr></table></figure><ul><li>方法的修饰符:方法的修饰符是可选的,main方法的修饰符是public static,代表公开的,静态的.方法的修饰符将在以后的章节中介绍 </li><li>方法的返回值类型:方法是一系列动作的组合,动作执行结束后可能会产生一个结果供其他程序使用,需要在方法定义时指定返回结果的类型,即方法返回值类型,main方法中没有返回值,返回值类型被定义为void </li><li>方法的名称,不需赘述,但请注意方法的名称遵循标示符的的命名规则,建议使用动词或动宾短语,首字母小写,驼峰式 </li><li>方法的参数列表,方法的名称后面紧跟着一个小括号,小括号中的内容称之为方法的参数,方法的参数可以为零个或者多个,详细内容在下面的章节介绍 </li><li>方法体,大括号之内的语句块称之为方法体 </li></ul><p>3.方法的使用 </p><ul><li>方法的调用语法 <ul><li>一般性的用法,静态方法与此略有不同 </li><li>同一个类中的方法可以不用”.”直接使用(本质上是使用了”this.”) <figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">对象.方法名([参数列表]);</span><br></pre></td></tr></table></figure></li></ul></li></ul><h5 id="方法的返回值"><a href="#方法的返回值" class="headerlink" title="方法的返回值"></a>方法的返回值</h5><p>1.要使方法对程序产生影响,方法给调用者一个返回值是必要的 </p><p><img src="/images/fangfa_return.png" alt></p><p>2.定义方法的时候,必须指定返回值类型,无返回值时,返回值类型为void </p><p><img src="/images/fangfa_no_return.png" alt></p><p>3.方法体内必须用return返回相应的返回值,返回值返回给方法的调用者 </p><p>4.无返回值的情况下(void),本质上是使用了return关键字结束方法,只是通常该语句省略了,return的作用是结束方法并返回,在方法执行过程中,只要遇到return就会结束方法并返回 </p><p>5.如果方法有返回值,那么在调用的时候,就可以用变量来接受该返回值,变量的类型即是方法定义时的返回值类型 </p><ul><li>举例: </li></ul><p><img src="/images/fangfafanhuileix.png" alt></p><h5 id="方法的参数"><a href="#方法的参数" class="headerlink" title="方法的参数"></a>方法的参数</h5><p>1.要使方法能够更加灵活的根据调用者的要求执行动作,调用者给方法一定的参数是必要的 </p><p><img src="/images/fangfacanshu.png" alt></p><p>2.参数列表用来向方法传入参数,需要指定参数的类型和名称,与变量定义的语法相同 </p><ul><li>举例: </li></ul><p><img src="/images/fangfachuanru.png" alt></p><p>3.带参数的方法的调用 </p><ul><li>带参数的方法在调用时需要传入参数,举例: </li></ul><p><img src="/images/daisanchufangfadiaoyong.png" alt></p><ul><li>一直在用的println()方法就是一个需要参数的方法,我们常常传入一个String型的字符串 </li><li>传入的参数必须是方法定义时指定的类型,参数顺序与定义时参数列表的顺序相同 </li></ul><p><img src="/images/20191010132654.png" alt></p><ul><li><p>方法中是由num1减去num2,所以最终的结果是由10减去1的值,而不是1减去10 </p></li><li><p>如上面的例子,程序运行中,方法参数列表中定义的num1和num2称为形式参数,在实际调用方法时传入的参数,10和1,称之为实际参数 </p></li><li><p>注意: </p><ul><li>实参对应的形参数量一致 </li><li>实参对应的形参数据类型一致 </li><li>当调用没有参数列表的方法时,方法后的()不能省略 </li><li>参数列表的设计要根据实际情况来定,参数太多,调用不便,参数太少,方法不灵活 </li><li>使用方法的目的是为了代码重用,因此设计时方法尽可能功能独立 </li></ul></li></ul><p>4.方法的可变参数 </p><ul><li>定义举例 </li></ul><p><img src="/images/20191010133619.png" alt></p><ul><li>注意:<ul><li>可变参数适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理 </li><li>可变参数必须位于参数列表的最后,一条参数列表中只能有一项可变参数 </li><li>调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数 </li></ul></li><li>可变参数方法的使用 </li></ul><p><img src="/images/20191010133828.png" alt></p><h5 id="基本数据类型和引用数据类型作为方法的参数"><a href="#基本数据类型和引用数据类型作为方法的参数" class="headerlink" title="基本数据类型和引用数据类型作为方法的参数"></a>基本数据类型和引用数据类型作为方法的参数</h5><p>1.基本数据类型作为方法的参数时,形参在方法中发生改变,不会影响实际参数的值 </p><p><img src="/images/20191010133932.png" alt></p><p>2.引用类型作为方法的参数时,形参在方法中发生改变,会影响到实际参数的值(String除外) </p><p><img src="/images/20191010134016.png" alt></p><h5 id="变量的作用域和生命周期"><a href="#变量的作用域和生命周期" class="headerlink" title="变量的作用域和生命周期"></a>变量的作用域和生命周期</h5><p>1.变量的作用域是指一个变量在定义后,在程序的什么地方可以使用它 </p><p>2.之前说过:变量的作用范围,在申明他的{}内有用,出了{},没有人认识它 </p><p>3.判断语句和循环语句中定义的变量,在当前的判断语句或循环语句的大括号之内有效;方法中定义的变量(局部变量),只能在当前方法使用;成员变量,对象实例化后可用,对象销毁后,内存也随之销毁,变量随之不可用 </p><p>4.方法内的局部变量(包括方法参数),如果与成员变量同名,方法中优先使用局部变量,这种情况下如果要使用成员变量,需要使用this关键字,this用来指向当前类的当前对象 </p><p><img src="/images/20191010134114.png" alt></p><h5 id="构造方法"><a href="#构造方法" class="headerlink" title="构造方法"></a>构造方法</h5><p><img src="/images/20191010134202.png" alt></p><p>1.构造方法是用来给new 关键字调用的,用来实例化对象,new关键字会在堆内存中开辟空间 </p><p>2.构造方法没有返回值,名称与类名相同 </p><p>3.系统默认为每个类提供无参的构造方法 </p><p>4.可以在构造方法中传入参数,在实例化对象时为对象的属性赋值 </p><p>5.如果提供了带参数的构造方法,系统不在默认提供无参构造方法,这时如果需要使用无参构造方法,需要人为提供 </p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之类与对象</title>
<link href="/3376612127.html"/>
<url>/3376612127.html</url>
<content type="html"><![CDATA[<h5 id="万物皆对象"><a href="#万物皆对象" class="headerlink" title="万物皆对象"></a>万物皆对象</h5><p>1.我们能感受到的万事万物都是一个个对象,都属于某一个类型 </p><p>2.对象具有各种各样的属性,同时也拥有各种各样的行为 </p><p>3.把一系列对象的共同特征和行为抽象出来,形成一个概念模型,就是类;也就是说:类是对象的抽象定义,对象是类的具体实例 </p><a id="more"></a><p>4.面向对象程序的本质就是:将程序设计成一个一个的类,定义出他们的特征和行为(即属性和方法),然后根据类创建出一个一个具体的对象,利用对象之间的关系进行调用,完成一系列的任务 </p><h5 id="类的定义"><a href="#类的定义" class="headerlink" title="类的定义"></a>类的定义</h5><p>1.java程序以class为组织单位 </p><p>2.关键字class用来定义类 </p><p><img src="/images/class_helloworld.png" alt></p><p>3.定义类的语法 </p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">[类修饰符] class 类名 { </span><br><span class="line"></span><br><span class="line">//定义属性部分 </span><br><span class="line"></span><br><span class="line">[属性修饰符] 属性1的类型 属性1; </span><br><span class="line"></span><br><span class="line">[属性修饰符] 属性2的类型 属性2; </span><br><span class="line"></span><br><span class="line">… </span><br><span class="line"></span><br><span class="line">[属性修饰符] 属性n的类型 属性n; </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">方法1; </span><br><span class="line"></span><br><span class="line">方法2; </span><br><span class="line"></span><br><span class="line">… </span><br><span class="line"></span><br><span class="line">方法m; </span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>4.注意:</p><ul><li>定义一个类的步骤:定义类名,编写属性,编写方法 </li><li>class是定义类的关键字 </li><li>类的命名规则,即标示符的命名规则,但为了阅读理解方便,约定不使用_,$等特殊字符,类名通常是名词性质,首字母大写,驼峰式 </li><li>属性的定义,与局部变量的定义相同,定义在类体内,方法体外,与方法平级,即全局变量 </li><li>有一点需要强调的是,类的属性,即全局变量,可以不初始化,在使用时,系统会默认初始化,整数均默认为0,小数默认为0.0,char默认为空格,boolean默认为false,引用类型默认为null </li><li>方法的定义,使用动词或动宾形式的短语,首字母小写,驼峰式命名 </li></ul><p>5.例子:定义一个学生类 </p><p><img src="/images/class_student_obj.png" alt></p><h5 id="如何创建和使用对象"><a href="#如何创建和使用对象" class="headerlink" title="如何创建和使用对象"></a>如何创建和使用对象</h5><p>1.定义类,实际上就是定义了一个新的数据类型,根据基本数据类型可以声明变量,自己申明的类也可以声明变量,称为对象 </p><p>2.声明一个对象的语法 </p><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">类名 对象名;</span><br></pre></td></tr></table></figure><p>3.声明后并没有给对象分配内存空间,要分配内存空间,需要使用new关键字 </p><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">类名 对象名 = new 类名();</span><br></pre></td></tr></table></figure><ul><li>声明对象并分配内存空间,即为类实例化(从一个抽象的类中具体中一个具体的实例) </li></ul><p>4.实例化对象后,可以访问对象的属性和方法 </p><figure class="highlight plain hljs"><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><br><span class="line"></span><br><span class="line">对象名.方法名([参数列表])</span><br></pre></td></tr></table></figure><p>实例化一个Student类的对象,并且赋值,调用方法: </p><p><img src="/images/classs_student_test.png" alt><br>5.注意: </p><ul><li>一个类可以实例化出多个对象,不同的对象在内存中是独立的,改变一个对象不会影响其他的对象 </li><li>上面我们看到的例子中,我们在main方法中根据自己定义的类声明了一个局部变量,事实上还可以声明成员变量 </li></ul><p><img src="/images/class_student_chenguan.png" alt></p><h5 id="使用类和对象的优点"><a href="#使用类和对象的优点" class="headerlink" title="使用类和对象的优点"></a>使用类和对象的优点</h5><p>1.与人类的思维习惯一致,把人类解决问题的思维过程转变为程序能够理解的过程 </p><p>2.提高了程序的可重用性,一个类可以创建多个对象实例,增加了重用性 </p><p>3.信息隐藏,提高了程序的可维护性和安全性 ,封装实现了模块化和信息隐藏 ,封装使得在对象外部不能随意访问对象的属性和方法(在学习了方法之后详细体会) </p><h5 id="打包和导入"><a href="#打包和导入" class="headerlink" title="打包和导入"></a>打包和导入</h5><p>1.打包 </p><ul><li>观察package语句 </li></ul><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">package com.phome.java.test1;</span><br></pre></td></tr></table></figure><ul><li>注意<ul><li>允许类组成较小的单元(类似文件夹),易于找到和使用相应的文件,方便管理 </li><li>防止命名冲突 </li><li>更好的保护类属性和方法 </li><li>包名之前最好加上唯一的前缀,通常使用组织倒置的网络域名 </li><li>一个类只能有一条package语句 </li></ul></li></ul><p>2.导入 </p><ul><li>为了使用不在同一个包中的类,java使用import关键字导入 </li><li>观察import语句 </li></ul><figure class="highlight plain hljs"><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">import com.phome.java.test2; </span><br><span class="line"></span><br><span class="line">import java.util.*;</span><br></pre></td></tr></table></figure><ul><li>系统包和自己定义的包 </li><li>使用”*”导入一个包中所有的类 </li></ul>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之String简介</title>
<link href="/56445.html"/>
<url>/56445.html</url>
<content type="html"><![CDATA[<h6 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h6><p>1.String是一个类型,用来存储一串字符的,本质上是一个char类型的数组 </p><p>2.String类在java.lang包中,lang包已经默认导入,我们不需要再用import导入了 </p><p>3.定义及赋初始值 </p><a id="more"></a><figure class="highlight plain hljs"><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">String 变量名 = "初始值"; </span><br><span class="line"></span><br><span class="line">String 变量名 = new String("初始值");</span><br></pre></td></tr></table></figure><ul><li>第二种方法不常用,推荐使用第一种 </li></ul><p>4.字符串可以进行”+”运算,作用是连接两个字符串,也可以将字符串与基本类型的变量进行”+”运算,系统会自动将基本类型的变量转换成字符串进行连接操作 </p><p>5.内存中的字符串,字符串的intern()方法,字符串比较 </p><p>6.注意:</p><ul><li>内存中的字符串,注意代码中没有new的字符串字面常量会在编译时编译进字符串池中 </li><li>intern()方法,返回字符串在字符串池中的位置,或者向字符串池中注册 </li><li>对于引用类型,==比较地址是否相同,equals()比较内容是否相同 </li></ul><h6 id="一些操作"><a href="#一些操作" class="headerlink" title="一些操作"></a>一些操作</h6><p>1.常用的方法</p><table><thead><tr><th>方法名称</th><th>返回类型</th><th>作用</th></tr></thead><tbody><tr><td>length()</td><td>int</td><td>获取字符串长度</td></tr><tr><td>charAt(int)</td><td>char</td><td>获取字符串中的一个字符</td></tr><tr><td>indexOf(String)</td><td>int</td><td>返回传入字符串在原字符串中第一次出现的位置</td></tr><tr><td>startWith(String)</td><td>boolean</td><td>判断原字符串是否以传入字符串开始</td></tr><tr><td>endsWith(String)</td><td>boolean</td><td>判断原字符串是否以传入字符串结束</td></tr><tr><td>toUpperCase()</td><td>String</td><td>变大写</td></tr><tr><td>substring()</td><td>String</td><td>截取字符串</td></tr><tr><td>trim()</td><td>String</td><td>去前后空格</td></tr><tr><td>split()</td><td>String[]</td><td>原字符串按特定字符串分割成一个字符串数组</td></tr><tr><td>…</td><td>…</td><td>…</td></tr></tbody></table><h6 id="字符串与基本数据类型的转换"><a href="#字符串与基本数据类型的转换" class="headerlink" title="字符串与基本数据类型的转换"></a>字符串与基本数据类型的转换</h6><p>1.基本类型装换为字符串,用一个空字符串”” 与基本类型的变量相加 </p><p>2.基本类型转换为字符串,使用String的ValueOf方法 </p><p>3.字符串转换为基本类型,使用各类型的包装类,char使用字符串的charAt()方法 </p><table><thead><tr><th>基本类型</th><th>包装类型</th><th>转化方法</th></tr></thead><tbody><tr><td>int</td><td>Interger</td><td>parseInt();</td></tr><tr><td>byte</td><td>Byte</td><td>parseByte();</td></tr><tr><td>short</td><td>Short</td><td>parseShort();</td></tr><tr><td>long</td><td>Long</td><td>parseLong();</td></tr><tr><td>float</td><td>Float</td><td>parseFloat();</td></tr><tr><td>double</td><td>Double</td><td>parseDouble();</td></tr><tr><td>boolean</td><td>Boolean</td><td>parseBoolean();</td></tr></tbody></table><h6 id="StringBuffer和StringBuilder"><a href="#StringBuffer和StringBuilder" class="headerlink" title="StringBuffer和StringBuilder"></a>StringBuffer和StringBuilder</h6><p>1.StringBuffe在对字符串操作时效率要远高于String </p><p>2.StringBuffer与StringBuilder用法相似,但StringBuffer线程安全,推荐使用 </p><p>3.StringBuffer的insert();append();delete()方法 </p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之数组</title>
<link href="/58759.html"/>
<url>/58759.html</url>
<content type="html"><![CDATA[<h6 id="数组的定义"><a href="#数组的定义" class="headerlink" title="数组的定义"></a>数组的定义</h6><p>1.什么是数组: </p><ul><li>数组是一个引用类型的变量,存储相同数据类型的一组数据 </li></ul><p>2.什么是声明变量 声明数组</p><a id="more"></a><ul><li>声明一个变量就是在内存空间划出一块合适的空间</li><li>声明一个数组就是在内存空间划出一串连续的空间 </li></ul><p><img src="/images/new_array_obj.png" alt></p><p>3.数组的结构和基本要素 </p><ul><li>标示符:数组的名称,用于区分不同的数组 </li><li>数组元素:在数组中存放的数据 </li><li>元素下标:对数组元素进行编号 </li><li>元素类型:数组元素的数据类型 </li></ul><h6 id="使用数组"><a href="#使用数组" class="headerlink" title="使用数组"></a>使用数组</h6><p>1.声明数组的语法 </p><figure class="highlight plain hljs"><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><br><span class="line">数据类型[] 数组名;</span><br></pre></td></tr></table></figure><p>2.注意:</p><ul><li>推荐使用后一种语法 </li><li>数据类型可以是基本数据类型,也可以是引用数据类型 </li><li>数组名遵循标示符的命名规范,建议使用名词的复数形式 </li><li>数组在声明时无法指定数组长途,因为数组声明在栈内存中 </li></ul><p>3.举例</p><p><img src="/images/new_array_eg.png" alt></p><p>4.给数组分配空间的语法 </p><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">数组名 = new 数据类型[数组长度];</span><br></pre></td></tr></table></figure><p>注意:</p><ul><li>数组声明后,并没有为它分配存储空间,要存入数据,必须要先分配存储空间 </li><li>给数组分配内存使用new关键字,会在堆内存中分配相应的空间 </li><li>数组的内存空间分配之后,长度无法改变,如果重新定义,会将之前的数组删除,建立新的数组 <ul><li>如下图第一句在堆内存中新建了一个长途为5的int类型的数组,并且赋值给nums 第二句重新在堆内存中新建了一个长度为7的int类型的数组,赋值给nums,之前的数组在堆内存中销毁了 </li></ul></li></ul><p><img src="/images/new_array_neicun.png" alt></p><p>5.数组赋值</p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">数据类型[] 数组名 = {数组元素}; 或 </span><br><span class="line"></span><br><span class="line">数据类型[] 数组名 = new 数据类型[]{数组元素} 或</span><br><span class="line"></span><br><span class="line">数组名[数组下标] = 数据值</span><br></pre></td></tr></table></figure><h6 id="数组的应用"><a href="#数组的应用" class="headerlink" title="数组的应用"></a>数组的应用</h6><p>1.求最大值</p><ul><li>原理,定义变量max,使用max和数组中的所有元素挨个比较,如果有元素的值大于max,就使max的值等于该元素的值,这样经过一轮比较够,max的值便是数组中最大的那个值. </li><li>算法举例(假设数组名为a): </li></ul><p><img src="/images/array_max_num.png" alt></p><p>2.冒泡排序</p><ul><li>原理,讲n个数从小到大排列,可以在第一次循环中找出最大的数放在数组的最后位置,在第二次循环中找出第二大的数放在数组的倒数第二个位置,…….,n-1次循环后,数组即从小到大排列了 </li></ul><p><img src="/images/maopaoyuanli.png" alt></p><ul><li>算法举例</li></ul><p><img src="/images/maopao_eg.png" alt></p><h6 id="再谈基本数据类型和引用数据类型"><a href="#再谈基本数据类型和引用数据类型" class="headerlink" title="再谈基本数据类型和引用数据类型"></a>再谈基本数据类型和引用数据类型</h6><p>1.java的内存是怎样的 </p><ul><li>Heap(堆,new出来的东西)</li><li>stack(栈,局部变量) </li><li>data segment(静态代码区,静态变量,字符串常量)</li><li>code segment(存放代码) </li></ul><p><img src="/images/chrngxuneicfenbutu.png" alt></p><p>2.基本数据类型:对于基本数据类型,不同的变量会分配不同的存储空间,改变一个变量的值不会影响其他变量的值;</p><p>3.引用数据类型:对于引用数据类型,不同的变量可能会指向同一块内存地址,改变一个变量的值可能会影响其他变量的值</p><h6 id="二维数组"><a href="#二维数组" class="headerlink" title="二维数组"></a>二维数组</h6><p>1.二维数组的每一个元素是另一个数组,本质上是指向另一个数组的引用<br>2.一维数组的内存结构 </p><p><img src="/images/yiwei_array_neicun.png" alt></p><p>3.二维数组的内存结构 </p><p><img src="/images/erwei_array_neicun.png" alt></p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之Java语言程序结构</title>
<link href="/5002.html"/>
<url>/5002.html</url>
<content type="html"><![CDATA[<p>前言: 程序想要完成更加强大的功能,只有流线型的顺序结构是不行的. 程序存在 顺序结构, 分支结构, 循环结构 这三种结构! </p><a id="more"></a><h5 id="结构简介"><a href="#结构简介" class="headerlink" title="结构简介"></a>结构简介</h5><p>1.顺序结构:按顺序执行 </p><p>2.分支结构(如图): </p><p><img src="/images/branch_structure.png" alt></p><p>3.循环结构(如图):</p><p><img src="/images/xunhuan.png" alt></p><h5 id="选择结构-if语句"><a href="#选择结构-if语句" class="headerlink" title="选择结构:if语句"></a>选择结构:if语句</h5><p>1.语法: </p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">if(条件表达式){ </span><br><span class="line"></span><br><span class="line">执行代码; </span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>2.结构: </p><p><img src="/images/if_structure.png" alt></p><p>3.当条件表达式为真的时候,执行{}中的代码</p><p>4.当执行代码只有一句时,可以省略{} </p><h5 id="选择结构-If-else和if-else-if-else"><a href="#选择结构-If-else和if-else-if-else" class="headerlink" title="选择结构:If-else和if-else if-else"></a>选择结构:If-else和if-else if-else</h5><p>1.语法:</p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">if(条件表达式){ </span><br><span class="line"></span><br><span class="line">执行代码A; </span><br><span class="line"></span><br><span class="line">}else{ </span><br><span class="line"></span><br><span class="line">执行代码B; </span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">if(条件表达式1){ </span><br><span class="line"></span><br><span class="line">执行代码A; </span><br><span class="line"></span><br><span class="line">}else if(条件表达式2){ </span><br><span class="line"></span><br><span class="line">执行代码B; </span><br><span class="line"></span><br><span class="line">}else{ </span><br><span class="line"></span><br><span class="line">执行代码C; </span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>2.结构 </p><p><img src="/images/if_else_structure.png" alt><br><img src="/images/if_else_if_structure.png" alt></p><p>3.注意</p><ul><li>注意代码的结构,做好缩进可以更容易的看出if,else的对应关系 </li><li>if语句可以嵌套 </li></ul><p>4.例子 如何判断是否为闰年 </p><ul><li>逻辑:整百的年份可以被400整除,为闰年,否则不是,其他年份被4整除为闰年,否则不是</li><li>代码演示:</li></ul><div align="center">![](/images/is_run_year_code.png)</div><h5 id="选择结构-三元表达式"><a href="#选择结构-三元表达式" class="headerlink" title="选择结构: 三元表达式"></a>选择结构: 三元表达式</h5><p>1.语法格式: </p><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(关系或者逻辑表达式)? 成立时的返回值:不成立时的返回值;</span><br></pre></td></tr></table></figure><p>2.例子 简化后判断是否为闰年</p><div align="center">![](/images/simplify_is_run_year_code.png)</div><p>3.注意: 虽然能简化代码,但是会提高代码的阅读难度,不建在复杂逻辑中议使用.</p><h5 id="选择结构-switch-case"><a href="#选择结构-switch-case" class="headerlink" title="选择结构:switch-case"></a>选择结构:switch-case</h5><p>1.语法: </p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">switch(表达式)</span><br><span class="line"></span><br><span class="line">{</span><br><span class="line"></span><br><span class="line"> case 值A:</span><br><span class="line"></span><br><span class="line"> 代码段A;</span><br><span class="line"></span><br><span class="line"> break;</span><br><span class="line"></span><br><span class="line"> case 值B:</span><br><span class="line"></span><br><span class="line"> 代码段B;</span><br><span class="line"></span><br><span class="line"> break;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> default:</span><br><span class="line"></span><br><span class="line"> 代码段F;</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>2.注意:</p><ul><li>表达式的值会与case子句中的值比较,如果相等则执行子句中的代码段,知道遇到break为止 </li><li>如果代码段中不写break,会执行后续case子句中的代码,即代码穿透现象 </li><li>如果没有case子句中的值与表达式的值相等,则执行default子句中的代码,default子句类似于else的作用 </li></ul><h5 id="循环结构-while循环"><a href="#循环结构-while循环" class="headerlink" title="循环结构:while循环"></a>循环结构:while循环</h5><p>1.语法: </p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">while(循环条件){ </span><br><span class="line"></span><br><span class="line">执行代码块.称之为"循环体"; </span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>2.while循环的结构 </p><p><img src="/images/while_structure.png" alt></p><p>3.while循环的执行顺序 :</p><ul><li>程序进入循环前,首先判断循环条件是否为true</li><li>如果循环条件为true,执行循环体中的代码,之后返回步骤1</li><li>如果循环条件为false,跳过循环体执行后面的代码 </li></ul><p>4.注意:</p><ul><li>循环条件是一个boolean类型的表达式,决定了什么条件下执行循环,什么条件下不执行循环 </li><li>为了避免死循环,一定会有循环变量,循环变量参与循环条件的判断,并且循环变量的值会在循环体内发生改变 </li></ul><h5 id="循环结构-do-while循环"><a href="#循环结构-do-while循环" class="headerlink" title="循环结构:do-while循环"></a>循环结构:do-while循环</h5><p>1.语法:</p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">do{ </span><br><span class="line"></span><br><span class="line">//执行代码; </span><br><span class="line"></span><br><span class="line">}while(循环条件)</span><br></pre></td></tr></table></figure><p>2.结构</p><p><img src="/images/do_while_structure.png" alt></p><p>3.do-while循环的执行顺序 </p><ul><li>执行循环体 </li><li>判断循环条件 </li><li>如果循环条件为true,返回步骤1 </li><li>如果循环条件为false,结束循环,执行后面的代码 </li></ul><p>4.注意: </p><ul><li>while循环中,首先判断循环条件,之后执行循环体;do-while循环中,先执行一次循环体,再判断循环条件 </li><li>do-while循环的循环体至少会被执行一次 </li><li>循环结构和分支结构可以嵌套,嵌套时注意大括号”{}”的匹配 </li></ul><h5 id="循环结构-for循环"><a href="#循环结构-for循环" class="headerlink" title="循环结构:for循环"></a>循环结构:for循环</h5><p>1.语法:</p><figure class="highlight plain hljs"><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></pre></td><td class="code"><pre><span class="line">for(表达式1; 表达式2; 表达式3){ </span><br><span class="line"></span><br><span class="line">//循环体 </span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>2.结构</p><p><img src="/images/for_structure.png" alt></p><p>3.for循环执行顺序 </p><ul><li>3.1.执行初始化部分 </li><li>3.2.进行循环条件判断 </li><li>3.3.根据循环条件判断结果,决定是否执行循环 </li><li>3.4.执行迭代部分.改变循环变量的值 </li><li>3.5.重复2,3,4部分,直至循环条件不成立 </li></ul><p>4.注意: </p><ul><li>不要出现死循环 </li><li>一般的,循环次数确定的可以选择for循环,循环次数不确定可以选择while循环 </li><li>for循环,do循环,do-while循环,分支选择语句可以相互嵌套 </li></ul><h5 id="跳转语句break和continue"><a href="#跳转语句break和continue" class="headerlink" title="跳转语句break和continue"></a>跳转语句break和continue</h5><p>1.break:如果在循环体中遇到break语句,会立刻跳出当前循环,继续执行后面的代码 </p><p>2.continue:如果在循环体中遇到continue语句,会立刻跳出本次循环,执行下一次循环 </p>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之变量,数据类型和运算符</title>
<link href="/558044812.html"/>
<url>/558044812.html</url>
<content type="html"><![CDATA[<h5 id="标示符"><a href="#标示符" class="headerlink" title="标示符"></a>标示符</h5><p>1.概念:就是标示变量,类等的名称的字符串序列 说白了就是程序中可以自己起名字的地方 </p><p>2.标示符的命名规则 </p><ul><li>由字母,下划线_,美元符号$或数字组成 </li><li>由字母,下划线_,美元符号$开始 </li><li>大小写敏感,长度无限制 <a id="more"></a></li><li>不能使用java关键字,goto和const虽然未被使用,但java也作为关键字保留 </li><li>不合法的标示符举例:class data# 78.9 </li></ul><p><img src="/images/java_crux.png" alt></p><p>3.约定:起名要做到”见名知意” </p><h5 id="常量"><a href="#常量" class="headerlink" title="常量"></a>常量</h5><p>1.字面常量:我们所能看到的真实的字面值 </p><ul><li>整型字面常量:10,123 </li><li>浮点型字面常量:3.14 </li><li>布尔型字面常量:true,false </li><li>字符型字面常量:’a’,’A’ </li><li>字符串型字面常量:”gansu” </li><li>Null型字面常量:值为null,代表什么都没有 </li></ul><p>2.在另一种语境下,常量的意思是值不可改变的变量,用final修饰,以后会遇到 </p><h5 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h5><p>1.概念:变量是程序中最基本的存储单元,实质是内存中的一小块区域,可以使用变量名来访问该一小块内存区域 </p><p>2.变量的定义和使用:变量先定义—>再赋值—>再使用 </p><figure class="highlight java hljs"><figcaption><span>[] []</span></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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">类型 变量名 [= 初始值]; </span><br><span class="line"><span class="hljs-keyword">int</span> a = <span class="hljs-number">30</span>; </span><br><span class="line"><span class="hljs-keyword">int</span> b = <span class="hljs-number">40</span>; </span><br><span class="line"><span class="hljs-keyword">int</span> c = a * b; </span><br><span class="line"><span class="hljs-keyword">int</span> d; </span><br><span class="line">d = <span class="hljs-number">50</span>; </span><br><span class="line"><span class="hljs-keyword">float</span> f = <span class="hljs-number">12.5f</span>; </span><br><span class="line">String s = <span class="hljs-string">"Hello"</span>; </span><br><span class="line"><span class="hljs-keyword">boolean</span> choice = <span class="hljs-keyword">true</span>; </span><br><span class="line">System.out.println(s); </span><br></pre></td></tr></table></figure><p>3.数据类型的概念:因为在变量中存储数据时会遇到各种各样的数据,所以有必要将不同的数据按照数据类型分开,方便分配内存空间和使用<br>4.变量的作用范围,在申明他的{}内有用,出了{},没有人认识它<br>5.变量的分类 </p><ul><li>按变量申明的位置划分<ul><li>局部变量:方法或语句块内部定义的变量 </li><li>成员变量:方法外部,类的内部定义的变量 </li></ul></li><li>按数据类型划分 <ul><li>基本数据类型的变量 </li><li>引用数据类型的变量 </li></ul></li></ul><h5 id="基本数据类型"><a href="#基本数据类型" class="headerlink" title="基本数据类型"></a>基本数据类型</h5><p>1.java语言提供了8种基本数据类型 </p><p><img src="/images/base_data_type.png" alt></p><p>2.说明: </p><ul><li>byte型,占用1个字节,对字节操作时使用,如文件读写等 </li><li>short型,占用2个字节,保存较小的整数时使用 </li><li>int型,占用4个字节,保存一般的整数时使用 </li><li>long型,占用8个字节,保存较长的整数时使用 </li><li>float型,占用4个字节保存小数时使用 </li><li>double型,占用8个字节,保存精度较高的小数时使用 </li><li>char型,占用2个字节,保存单个字母或汉字时使用 </li><li>boolean型,占用1个字节,保存逻辑值,如性别,婚否等 </li><li>类型定义好之后,后续无法改变,所以定义变量时要根据实际情况选择好变量的数据类型 </li></ul><p>3.特殊字符的说明,char类型可以保存一个字符(字母或汉字),一些特殊字符在保存时可以采用转义字符”": </p><figure class="highlight java hljs"><figcaption><span>[] []</span></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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="hljs-keyword">char</span> a = <span class="hljs-string">'\n'</span>; <span class="hljs-comment">//换行 </span></span><br><span class="line"></span><br><span class="line"><span class="hljs-keyword">char</span> b = <span class="hljs-string">'\\'</span>; <span class="hljs-comment">//反斜杠 </span></span><br><span class="line"></span><br><span class="line">Char c = <span class="hljs-string">'\''</span>; <span class="hljs-comment">//单引号 </span></span><br></pre></td></tr></table></figure><p>4.注意java会默认将整型的字面常量认作int类型,将浮点型的字面常量认作double类型,申明long类型时要在后面加L,申明float类型时要在后面加F </p><p>5.一个特殊的类型:String类型。 String并不是java的基础数据类型,不过是一个很常用的类型,用来存储字符串变量。</p><h5 id="运算符"><a href="#运算符" class="headerlink" title="运算符"></a>运算符</h5><p>如果说数据类型是编程语言的砖瓦,那么运算符和操作符则是编程语言的石灰和水泥了,它是将各种数据类型的值有机组合的糅,使得数据值不再只是一个孤立的值,而有了一种动态的灵性. </p><p>1.赋值运算符和常见算数运算符 </p><table><thead><tr><th>运算符</th><th>说明</th><th>示例</th></tr></thead><tbody><tr><td>=</td><td>赋值运算符,为变量赋值</td><td>int a = 3;</td></tr><tr><td>+</td><td>加法运算符,求两个操作数的和</td><td>3+2,表达式的值为5</td></tr><tr><td>-</td><td>减法运算符,求两个操作数的差</td><td>6-1,表达式的值为5</td></tr><tr><td>*</td><td>乘法运算符,求两个操作数的积</td><td>2*3,表达式的值为6</td></tr><tr><td>/</td><td>除法运算符,求两个操作数的商</td><td>8/4,表达式的值为2</td></tr><tr><td>%</td><td>求余运算符,求两个操作数相除后的余数</td><td>9%5,表达式的值是4</td></tr><tr><td>++</td><td>自增运算符,对一个整数变量执行+1的操作</td><td>int a = 3;3++或++3的值都是4</td></tr><tr><td>–</td><td>自减运算符,对一个整数变量执行-1的操作</td><td>int a = 3;3–或–3的值都是2</td></tr></tbody></table><p>2.求余运算符要求两个操作数均为整数,但测试的结果好像浮点型的也可以,不重要. </p><p>3.注意整除和浮点除的区别:两个操作数全是int型,结果也是int型,会丢失小数部分,</p><p>4.注意++和–运算,a++表示先使用a的值,再给a加上1;++a表示先给a加上1,再使用a的值,–与此类似 </p><p>5.是时候扩展我们程序的功能了,看看Scanner类,注意Scanner对象的一些常用方法,如nextInt() </p><p>6.关系运算符</p><table><thead><tr><th>==</th><th>!=</th><th>></th><th>>=</th><th><</th><th><=</th></tr></thead><tbody><tr><td>等于</td><td>不等于</td><td>大于</td><td>大于等于</td><td>小于</td><td>小于等于</td></tr></tbody></table><p>7.逻辑运算符 </p><table><thead><tr><th>运算符</th><th>操作数</th><th>运算规则</th></tr></thead><tbody><tr><td>逻辑与&&</td><td>2</td><td>两个操作数均为true,则结果为true,否则结果为false</td></tr><tr><td>逻辑或||</td><td>2</td><td>两个操作数中只有一个为true则结果为true,否则结果为false</td></tr><tr><td>逻辑非!</td><td>1</td><td>操作数为true则结果为false,操作数为false则结果为true</td></tr></tbody></table><p>8.在逻辑与&&运算中,当第一个操作数返回false,直接返回false,不再进行第二个操作数的运算;在进行逻辑或||运算时,当第一操作数返回true,直接返回true,不再进行第二个操作数的运算 </p><p>9.复合赋值运算符(假设a = 10) </p><table><thead><tr><th>表达式</th><th>等价的java代码</th><th>运行的结果</th></tr></thead><tbody><tr><td>a += 3;</td><td>a = a + 3;</td><td>13</td></tr><tr><td>a -= a /= 3;</td><td>a = a / 3;</td><td>3</td></tr><tr><td>a %= 3;</td><td>a = a % 3;</td><td>3</td></tr></tbody></table><p>10.运算符的优先级 <code>注意:千万不要去记这个,有个印象就行,实际写代码的时候请使用().</code></p><table><thead><tr><th>优先级</th><th>运算符</th></tr></thead><tbody><tr><td>1</td><td>() [] .</td></tr><tr><td>2</td><td>! +(正) -(负) ~ ++ –</td></tr><tr><td>3</td><td>* / %</td></tr><tr><td>4</td><td>+(加) -(减)</td></tr><tr><td>5</td><td><< >> >>></td></tr><tr><td>6</td><td>< <= > >= instanceof</td></tr><tr><td>7</td><td>== !=</td></tr><tr><td>8</td><td>&(按位与)</td></tr><tr><td>9</td><td>^</td></tr><tr><td>10</td><td>|</td></tr><tr><td>11</td><td>&&</td></tr><tr><td>12</td><td>| |</td></tr><tr><td>13</td><td>?:(三元表达式)</td></tr><tr><td>14</td><td>= += -= *= /= %= &=</td></tr></tbody></table><h5 id="数据类型转换"><a href="#数据类型转换" class="headerlink" title="数据类型转换"></a>数据类型转换</h5><p>1.自动数据类型转换 </p><ul><li>java基础变量按照分配内存空间从小到大的顺序排列,如图</li><li>在一个表达式中,如果含有不同数据类型的数据,自动按照从左向右,从下向上的顺序转换类型 </li><li>请注意表达式结果的数据类型 </li><li>boolean类型不参与数据类型转换 </li><li>低级别的数据类型可以轻松的转换为高级别的数据类型 </li></ul><p><img src="/images/data_type_conversion.png" alt></p><p>2.强制数据类型转换 </p><ul><li>同一级别,高级别向低级别的数据类型转换,需要强制 </li><li>转换过程中会丢失数据 </li><li>字符串String与其他数据类型用 +号连接时,都会将其他数据类型先转换为String,然后两个字符串拼接 </li></ul>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
<entry>
<title>一起学java之jdk的安装</title>
<link href="/3105940755.html"/>
<url>/3105940755.html</url>
<content type="html"><![CDATA[<h5 id="Java的历史"><a href="#Java的历史" class="headerlink" title="Java的历史"></a>Java的历史</h5><p>1.1991年,sun公司,”Green”项目,智能家电,JGosling(詹姆斯·高斯林),C++ —> Oak(橡树)起初濒临”倒闭”,internet开始流行 </p><p>2.94年,Oak改名java(印度尼西亚爪哇岛,盛产咖啡,咖啡宝贝),开发了HotJava浏览器,95年java正式推出发布</p><a id="more"></a><p>3.java具有能够跨平台,面向对象等特性,sun又将java设计为可以针对不同应用场景的综合开发平台,使之快速流行 </p><p>4.学习了java基本语言特性后,可以学习不同的开发包,进行不同平台的开发 </p><ul><li>Java SE:桌面应用开发</li><li>Java EE:企业级开发</li><li>Java ME:移动平台开发(手机等) </li><li>J2SE1.1 —-> J2SE1.5 改名 java SE 5.0 </li><li>09年,甲骨文收购sun,取得java版权 </li><li>如今免费版本止步与第8版 </li></ul><h5 id="java的优势"><a href="#java的优势" class="headerlink" title="java的优势"></a>java的优势</h5><p>1.面向对象—-使之特别适用用复杂,庞大的应用软件开发 </p><p>2.平台无关—-代码不用修改即可应用于不同的平台</p><p>3.健壮,安全—-完善的内存管理机制 </p><h5 id="开发前准备-安装配置JDK"><a href="#开发前准备-安装配置JDK" class="headerlink" title="开发前准备(安装配置JDK)"></a>开发前准备(安装配置JDK)</h5><p>1.安装jdk</p><ul><li>首先下载一个jdk,去官网找(注意sun被oracle收购了,应该去oracle的官网) </li><li>JDK 全称为Java Development Kit ,即java开发工具包.JRE 全称为Java RunTime Environment ,即java运行时环境 ,JDK中即包含一个JRE </li><li>bin目录下存放了运行,编译,调试java程序的必需的各种可执行文件 </li><li>lib目录下是java的各种开发类库 </li></ul><p><img src="/images/GetImage.png" alt></p><h5 id="配置环境变量"><a href="#配置环境变量" class="headerlink" title="配置环境变量"></a>配置环境变量</h5><p>1.鼠标右击我的电脑–>属性–>高级系统设置–>环境变量 </p><ul><li>JAVA_HOME=C:\Program Files\Java\jdk1.7.0_21; </li><li>CLASSPATH=.;%JAVA_HOME%\lib;(注意不要忘了代表当前目录的 .; ) </li><li>Path=原变量值;%JAVA_HOME%\bin;(注意不要删除以前的值) </li><li>命令行输入java和javac命令进行验证</li></ul><p><img src="/images/run_sysetm.png" alt></p><h5 id="java的运行机制-简单"><a href="#java的运行机制-简单" class="headerlink" title="java的运行机制(简单)"></a>java的运行机制(简单)</h5><p> java运行平台,即java虚拟机(java Virtual Machine),不同的平台有不同的JVM,不同的JVM可以运行相同的.class文件<br>这样,java即做到了跨平台,可以”Write once , run anywhere”.<br><img src="/images/java_run.png" alt></p><h5 id="HelloWorld"><a href="#HelloWorld" class="headerlink" title="HelloWorld"></a>HelloWorld</h5><p>1.第一个java小程序 </p><ul><li>使用IDEA,新建一个Hello.java文件</li><li>输入以下代码 </li></ul><p><img src="/images/java_helloword_code.png" alt></p><p>2.一些说明 </p><ul><li>java严格区分大小写,请注意大小写字母 </li><li>//单行注释,注释的内容在编译的时候忽略,只是为了自己阅读方便 </li><li>关键字class声明了一个类,名称为Hello,public修饰该类为公有,java中要求公有类的名称和文件名必须相同,且一个.java文件中只有一个公有类 </li><li>main方法是java程序的入口,程序从这里开始运行 </li><li>System.out.println();用于在控制台输出语句,输出后换行,没有末尾的System.out.print();为不换行输出,可以使用\n换行 </li><li>执行语句在方法体内,用{}包括,方法在类中,用{}包括 </li><li>括号必须成对出现,一行只写一条语句,注意代码的缩进和建筑美 </li></ul>]]></content>
<categories>
<category> 一起学java </category>
</categories>
<tags>
<tag> JAVA </tag>
</tags>
</entry>
</search>