Java?Timer使用講解
Timer 詳解
Timer 和 TimerTask 用于在后臺(tái)線(xiàn)程中調(diào)度任務(wù)的 java.util 類(lèi)。 TimerTask 負(fù)責(zé)任務(wù)的執(zhí)行, Timer 負(fù)責(zé)任務(wù)的調(diào)度。
定時(shí)功能
Timer 提供了三種定時(shí)模式:
fixed delay fixed rate
java.util包下提供了對(duì)定時(shí)任務(wù)的支持,涉及2個(gè)類(lèi):
- Timer:定時(shí)器類(lèi)
- TimerTask:任務(wù)抽象類(lèi)
使用該定時(shí)任務(wù)我們需要繼承TimerTask抽象類(lèi),覆蓋run方法編寫(xiě)任務(wù)執(zhí)行代碼,并利用Timer定時(shí)器對(duì)TimerTask進(jìn)行調(diào)度。
編寫(xiě)一個(gè)任務(wù):
TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println(DateUtil.formatNow() + " " + Thread.currentThread().getName() + " task run ");
}
};接著使用Timer對(duì)TimerTask進(jìn)行調(diào)度,Timer提供了多種方法,可分為一次性任務(wù)和可重復(fù)執(zhí)行任務(wù)。
一、一次性任務(wù)
一次性任務(wù)是指Timer執(zhí)行一次之后,該任務(wù)后續(xù)不再執(zhí)行。
一次性任務(wù)包括2個(gè)方法,如下:
- voidschedule(TimerTasktask,longdelay):延遲delay毫秒后執(zhí)行一次task
- voidschedule(TimerTasktask,Datetime):在指定時(shí)間time執(zhí)行一次task,如果time過(guò)期,將會(huì)立即執(zhí)行
二、可重復(fù)執(zhí)行任務(wù)
可重復(fù)執(zhí)行任務(wù)是指,任務(wù)允許按照設(shè)定的規(guī)則重復(fù)執(zhí)行。
可重復(fù)執(zhí)行任務(wù)共有4個(gè)方法,分為固定延時(shí) schedule和固定速率 scheduleAtFixedRate:
- voidschedule(TimerTasktask,longdelay,longperiod):延遲delay毫秒后執(zhí)行task,之后每隔period毫秒執(zhí)行一次task
- voidschedule(TimerTasktask,DatefirstTime,longperiod):在指定時(shí)間time執(zhí)行一次task,之后每隔period毫秒執(zhí)行一次task
- voidscheduleAtFixedRate(TimerTasktask,longdelay,longperiod):延遲delay毫秒后執(zhí)行task,之后每隔period毫秒執(zhí)行一次task
- voidscheduleAtFixedRate(TimerTasktask,DatefirstTime,longperiod):在指定時(shí)間time執(zhí)行一次task,之后每隔period毫秒執(zhí)行一次task
示例1:schedule方法,延遲delay毫秒后執(zhí)行task,之后每隔period毫秒執(zhí)行一次task
System.out.println("啟動(dòng)于:" + DateUtil.formatNow());
Timer timer = new Timer("timer");
timer.schedule(task, 1000, 2000);輸出:
啟動(dòng)于:2022-10-31 10:05:15
2022-10-31 10:05:16 timer task run
2022-10-31 10:05:18 timer task run
2022-10-31 10:05:20 timer task run
示例2:schedule在指定時(shí)間time執(zhí)行一次task,之后每隔period毫秒執(zhí)行一次task
System.out.println("啟動(dòng)于:" + DateUtil.formatNow());
Timer timer = new Timer("timer");
timer.schedule(task, DateUtil.parse("2022-10-31 10:07:00", DateUtil.YYYY_MM_DD_HH24_MM_SS), 2000);輸出:
啟動(dòng)于:2022-10-31 10:06:39
2022-10-31 10:07:00 timer task run
2022-10-31 10:07:02 timer task run
2022-10-31 10:07:04 timer task run
固定延時(shí) schedule 和 固定速率 scheduleAtFixedRate 在正常情況下看起來(lái)功能基本是一致的,區(qū)別在于當(dāng)任務(wù)耗時(shí)超出執(zhí)行時(shí)間間隔period,后續(xù)任務(wù)被延誤時(shí),schedule和scheduleAtFixedRate的處理方式不同,后面介紹。
三、固定延時(shí)和固定速率區(qū)別(重點(diǎn))
1. 介紹
由于Timer內(nèi)部?jī)H維護(hù)一個(gè)線(xiàn)程來(lái)執(zhí)行所有任務(wù),所以當(dāng)前一個(gè)任務(wù)耗時(shí)過(guò)長(zhǎng),可能會(huì)導(dǎo)致后一個(gè)任務(wù)的執(zhí)行被延誤。
出現(xiàn)任務(wù)延誤的情況下,固定延時(shí) schedule和 固定速率 scheduleAtFixedRate 的區(qū)別就在于,schedule會(huì)順延,而scheduleAtFixedRate會(huì)把延誤任務(wù)立馬補(bǔ)上。
在網(wǎng)上看到幾個(gè)非常恰當(dāng)?shù)睦?,貼上來(lái)加深理解。
例1:
暑假到了老師給schedule和scheduleAtFixedRate兩個(gè)同學(xué)布置作業(yè)。
老師要求學(xué)生暑假每天寫(xiě)2頁(yè),30天后完成作業(yè)。
這兩個(gè)學(xué)生每天按時(shí)完成作業(yè),直到第10天,出了意外,兩個(gè)學(xué)生出去旅游花了5天時(shí)間,這5天時(shí)間里兩個(gè)人都沒(méi)有做作業(yè)。任務(wù)被拖延了。
這時(shí)候兩個(gè)學(xué)生采取的策略就不同了:
schedule重新安排了任務(wù)時(shí)間,旅游回來(lái)的第一天做第11天的任務(wù),第二天做第12天的任務(wù),最后完成任務(wù)花了35天。
scheduleAtFixedRate是個(gè)守時(shí)的學(xué)生,她總想按時(shí)完成老師的任務(wù),于是在旅游回來(lái)的第一天把之前5天欠下的任務(wù)以及第16天當(dāng)天的任務(wù)全部完成了,之后還是按照老師的原安排完成作業(yè),最后完成任務(wù)花了30天。
例2:
固定速率就好比你今天加班到很晚,但是到了第二天還必須準(zhǔn)點(diǎn)到公司上班,如果你一不小心加班到了第二天早上 9 點(diǎn),你就連休息的時(shí)間都沒(méi)有了。
而固定時(shí)延的意思是你必須睡夠 8 個(gè)小時(shí)再過(guò)來(lái)上班,如果你加班到凌晨 6 點(diǎn),那就可以下午過(guò)來(lái)上班了。
固定速率強(qiáng)調(diào)準(zhǔn)點(diǎn),固定時(shí)延強(qiáng)調(diào)間隔。
如果任務(wù)必須每天準(zhǔn)點(diǎn)調(diào)度,那就應(yīng)該使用固定速率調(diào)度,并且要確保每個(gè)任務(wù)執(zhí)行時(shí)間不要太長(zhǎng),避免超過(guò)period間隔。
如果任務(wù)需要每隔幾分鐘跑一次,那就使用固定時(shí)延調(diào)度,它不是很在乎單個(gè)任務(wù)要跑多長(zhǎng)時(shí)間。
我們來(lái)模擬一下這個(gè)情況。
首先,我們對(duì)TimerTask進(jìn)行修改,讓它某一次任務(wù)產(chǎn)生大量耗時(shí):
TimerTask task = new TimerTask() {
private int i = 1;
@Override
public void run() {
System.out.print(i + " " + DateUtil.formatNow() + " 開(kāi)始執(zhí)行, ");
if(i == 3) {
ThreadUtil.sleep(11 * 1000);
}
System.out.println(DateUtil.formatNow() + " 結(jié)束");
i++;
}
};該任務(wù)在執(zhí)行第3次時(shí),將會(huì)休眠11秒,這將會(huì)導(dǎo)致延誤后續(xù)的任務(wù)。
2. 固定速率
示例:
Timer timer = new Timer("timer");
timer.scheduleAtFixedRate(task, 5000, 2000);設(shè)定任務(wù)延遲5秒后執(zhí)行第1次任務(wù),之后每2秒執(zhí)行一次。
輸出:
啟動(dòng)于:2022-10-31 15:51:24
1 2022-10-31 15:51:29 開(kāi)始執(zhí)行, 2022-10-31 15:51:29 結(jié)束
2 2022-10-31 15:51:31 開(kāi)始執(zhí)行, 2022-10-31 15:51:31 結(jié)束
3 2022-10-31 15:51:33 開(kāi)始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
4 2022-10-31 15:51:44 開(kāi)始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
5 2022-10-31 15:51:44 開(kāi)始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
6 2022-10-31 15:51:44 開(kāi)始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
7 2022-10-31 15:51:44 開(kāi)始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
8 2022-10-31 15:51:44 開(kāi)始執(zhí)行, 2022-10-31 15:51:44 結(jié)束 *
9 2022-10-31 15:51:45 開(kāi)始執(zhí)行, 2022-10-31 15:51:45 結(jié)束
10 2022-10-31 15:51:47 開(kāi)始執(zhí)行, 2022-10-31 15:51:47 結(jié)束
11 2022-10-31 15:51:49 開(kāi)始執(zhí)行, 2022-10-31 15:51:49 結(jié)束
如果不存在第3次耗時(shí)11秒的情況下,正常任務(wù)執(zhí)行時(shí)間應(yīng)該為:
啟動(dòng)于:2022-10-31 15:51:24
1 2022-10-31 15:51:29 開(kāi)始執(zhí)行, 2022-10-31 15:51:29 結(jié)束
2 2022-10-31 15:51:31 開(kāi)始執(zhí)行, 2022-10-31 15:51:31 結(jié)束
3 2022-10-31 15:51:33 開(kāi)始執(zhí)行, 2022-10-31 15:51:33 結(jié)束 *
4 2022-10-31 15:51:35 開(kāi)始執(zhí)行, 2022-10-31 15:51:35 結(jié)束 *
5 2022-10-31 15:51:37 開(kāi)始執(zhí)行, 2022-10-31 15:51:37 結(jié)束 *
6 2022-10-31 15:51:39 開(kāi)始執(zhí)行, 2022-10-31 15:51:39 結(jié)束 *
7 2022-10-31 15:51:41 開(kāi)始執(zhí)行, 2022-10-31 15:51:41 結(jié)束 *
8 2022-10-31 15:51:43 開(kāi)始執(zhí)行, 2022-10-31 15:51:43 結(jié)束 *
9 2022-10-31 15:51:45 開(kāi)始執(zhí)行, 2022-10-31 15:51:45 結(jié)束
10 2022-10-31 15:51:47 開(kāi)始執(zhí)行, 2022-10-31 15:51:47 結(jié)束
11 2022-10-31 15:51:49 開(kāi)始執(zhí)行, 2022-10-31 15:51:49 結(jié)束
但是在第3次執(zhí)行任務(wù)時(shí)因?yàn)閳?zhí)行耗時(shí)11秒,第4次本該在15:51:35開(kāi)始執(zhí)行并完成任務(wù),卻到了15:51:44才執(zhí)行完成,這11秒延誤了后續(xù)5個(gè)任務(wù)的正常執(zhí)行,因此在15:51:44時(shí),scheduleAtFixedRate趕作業(yè)把延誤的5個(gè)任務(wù)一起執(zhí)行了。
最后趕上了原本的進(jìn)度,第9個(gè)任務(wù)準(zhǔn)時(shí)在15:51:45執(zhí)行。
3. 固定延時(shí)
示例:
Timer timer = new Timer("timer");
timer.schedule(task, 5000, 2000);輸出:
啟動(dòng)于:2022-10-31 15:56:59
1 2022-10-31 15:57:04 開(kāi)始執(zhí)行, 2022-10-31 15:57:04 結(jié)束
2 2022-10-31 15:57:06 開(kāi)始執(zhí)行, 2022-10-31 15:57:06 結(jié)束
3 2022-10-31 15:57:08 開(kāi)始執(zhí)行, 2022-10-31 15:57:19 結(jié)束 *
4 2022-10-31 15:57:19 開(kāi)始執(zhí)行, 2022-10-31 15:57:19 結(jié)束
5 2022-10-31 15:57:21 開(kāi)始執(zhí)行, 2022-10-31 15:57:21 結(jié)束
6 2022-10-31 15:57:24 開(kāi)始執(zhí)行, 2022-10-31 15:57:24 結(jié)束
7 2022-10-31 15:57:26 開(kāi)始執(zhí)行, 2022-10-31 15:57:26 結(jié)束
8 2022-10-31 15:57:28 開(kāi)始執(zhí)行, 2022-10-31 15:57:28 結(jié)束
9 2022-10-31 15:57:30 開(kāi)始執(zhí)行, 2022-10-31 15:57:30 結(jié)束
10 2022-10-31 15:57:32 開(kāi)始執(zhí)行, 2022-10-31 15:57:32 結(jié)束
如果不存在第3次耗時(shí)11秒的情況下,正常任務(wù)執(zhí)行時(shí)間應(yīng)該為:
啟動(dòng)于:2022-10-31 15:56:59
1 2022-10-31 15:57:04 開(kāi)始執(zhí)行, 2022-10-31 15:57:04 結(jié)束
2 2022-10-31 15:57:06 開(kāi)始執(zhí)行, 2022-10-31 15:57:06 結(jié)束
3 2022-10-31 15:57:08 開(kāi)始執(zhí)行, 2022-10-31 15:57:08 結(jié)束 *
4 2022-10-31 15:57:10 開(kāi)始執(zhí)行, 2022-10-31 15:57:10 結(jié)束
5 2022-10-31 15:57:12 開(kāi)始執(zhí)行, 2022-10-31 15:57:12 結(jié)束
6 2022-10-31 15:57:14 開(kāi)始執(zhí)行, 2022-10-31 15:57:14 結(jié)束
7 2022-10-31 15:57:16 開(kāi)始執(zhí)行, 2022-10-31 15:57:16 結(jié)束
8 2022-10-31 15:57:18 開(kāi)始執(zhí)行, 2022-10-31 15:57:18 結(jié)束
9 2022-10-31 15:57:20 開(kāi)始執(zhí)行, 2022-10-31 15:57:20 結(jié)束
10 2022-10-31 15:57:22 開(kāi)始執(zhí)行, 2022-10-31 15:57:22 結(jié)束
使用schedule調(diào)度,第4次任務(wù)本該在15:57:10開(kāi)始執(zhí)行,但由于耗時(shí)11秒直到15:57:19才開(kāi)始。
而第3次任務(wù)實(shí)際是在19秒完成,完成后又在19秒立即執(zhí)行第4次,中間少了2秒間隔,第4次完成后接著開(kāi)始2秒一次,變?yōu)榱藦?1秒開(kāi)始執(zhí)行第5次。
和我原本的推測(cè)不一樣的是,本以為19秒完成后,第4次會(huì)隔2秒在21秒執(zhí)行,沒(méi)想到19秒會(huì)立即執(zhí)行。
猜測(cè)與delay參數(shù)有關(guān),但調(diào)整了delay后仍然一樣,完成的那一秒還是會(huì)馬上再執(zhí)行第4次任務(wù)。
通過(guò)以上測(cè)試對(duì)比,我們可以感受到Timer中固定速率和固定延時(shí)的區(qū)別,但為了避免出錯(cuò),使用Timer時(shí)應(yīng)讓TimerTask耗時(shí)盡可能短。
4. 其他要點(diǎn)
1.以上是僅第3次任務(wù)加上了耗時(shí)11秒,如果是所有任務(wù)都耗時(shí)11秒呢?
如果每次任務(wù)執(zhí)行都耗時(shí)11秒,那么無(wú)論是固定速率還是固定延時(shí),都將是11秒執(zhí)行一個(gè)任務(wù)。
2.如果改為schedule(TimerTasktask,DatefirstTime,longperiod)和scheduleAtFixedRate(TimerTasktask,DatefirstTime,longperiod)來(lái)調(diào)度任務(wù),firstTime指定為10點(diǎn),而當(dāng)前系統(tǒng)時(shí)間為11點(diǎn),會(huì)出現(xiàn)什么情況呢?
雖然firstTime已經(jīng)過(guò)期,但是Timer將會(huì)立即開(kāi)始執(zhí)行任務(wù),之后按照period間隔重復(fù)執(zhí)行任務(wù)。
3.如果TimerTask執(zhí)行過(guò)程中拋出了異常會(huì)發(fā)生什么事情?
Timer內(nèi)部?jī)H維護(hù)一個(gè)線(xiàn)程,當(dāng)任一TimerTask拋出異常,將導(dǎo)致此線(xiàn)程終止運(yùn)行,該Timer負(fù)責(zé)的所有任務(wù)都無(wú)法執(zhí)行。
四、調(diào)度多個(gè)TimerTask
在上一節(jié)中,介紹的是一個(gè)可重復(fù)執(zhí)行的TimeTask,如果執(zhí)行耗時(shí)大于設(shè)定的間隔period,將會(huì)影響該TimerTask下一次執(zhí)行的時(shí)間點(diǎn)。
而這一節(jié)則是為了單獨(dú)說(shuō)明,一個(gè)Timer同時(shí)調(diào)度多個(gè)TimeTask也會(huì)互相影響。
示例:
TimerTask task1 = new TimerTask() {
private int i = 1;
@Override
public void run() {
System.out.print(i + " task1:" + DateUtil.formatNow() + " 開(kāi)始執(zhí)行, ");
ThreadUtil.sleep(11 * 1000);
System.out.println(DateUtil.formatNow() + " 結(jié)束");
i++;
}
};
TimerTask task2 = new TimerTask() {
private int i = 1;
@Override
public void run() {
System.out.print(i + " task2:" + DateUtil.formatNow() + " 開(kāi)始執(zhí)行, ");
ThreadUtil.sleep(11 * 1000);
System.out.println(DateUtil.formatNow() + " 結(jié)束");
i++;
}
};
Timer timer = new Timer("timer");
timer.scheduleAtFixedRate(task1, 5000, 2000);
timer.scheduleAtFixedRate(task2, 5000, 2000);輸出:
1 task1:2022-10-31 16:58:27 開(kāi)始執(zhí)行, 2022-10-31 16:58:38 結(jié)束
1 task2:2022-10-31 16:58:38 開(kāi)始執(zhí)行, 2022-10-31 16:58:49 結(jié)束
2 task2:2022-10-31 16:58:49 開(kāi)始執(zhí)行, 2022-10-31 16:59:00 結(jié)束
2 task1:2022-10-31 16:59:00 開(kāi)始執(zhí)行, 2022-10-31 16:59:11 結(jié)束
3 task1:2022-10-31 16:59:11 開(kāi)始執(zhí)行, 2022-10-31 16:59:22 結(jié)束
3 task2:2022-10-31 16:59:22 開(kāi)始執(zhí)行, 2022-10-31 16:59:33 結(jié)束
4 task2:2022-10-31 16:59:33 開(kāi)始執(zhí)行, 2022-10-31 16:59:44 結(jié)束
4 task1:2022-10-31 16:59:44 開(kāi)始執(zhí)行, 2022-10-31 16:59:55 結(jié)束
可以發(fā)現(xiàn),task1和task2其實(shí)都沒(méi)有按照既定時(shí)間去執(zhí)行任務(wù)了。
根本原因是在于,Timer內(nèi)部?jī)H維護(hù)一個(gè)線(xiàn)程執(zhí)行所有TimerTask,為了避免錯(cuò)誤,一個(gè)Timer對(duì)象最好僅調(diào)度一個(gè)TimerTask對(duì)象,除非可以確保多個(gè)TimerTask之間一定不會(huì)相互影響。
因此編寫(xiě)TimerTask時(shí)應(yīng)當(dāng)自行捕獲異常。
五、取消任務(wù)
Timer在創(chuàng)建時(shí)實(shí)際上是默認(rèn)在內(nèi)部維護(hù)了一個(gè)非守護(hù)線(xiàn)程,即使任務(wù)全部執(zhí)行完成,線(xiàn)程也并不會(huì)銷(xiāo)毀。
Timer提供cancel()方法,可以手動(dòng)調(diào)用取消定時(shí)器所有的任務(wù),并銷(xiāo)毀定時(shí)器。
如果想要Timer內(nèi)部創(chuàng)建的是守護(hù)線(xiàn)程,可以使用以下構(gòu)造方法創(chuàng)建定時(shí)器,設(shè)置isDaemon為true:
- Timer(booleanisDaemon)
Timer(Stringname,booleanisDaemon)
如果沒(méi)有自己定義name參數(shù),默認(rèn)Timer內(nèi)部自動(dòng)命名為“Timer-遞增序號(hào)”,作為內(nèi)部線(xiàn)程的線(xiàn)程名稱(chēng),在構(gòu)造方法內(nèi)啟動(dòng)此線(xiàn)程。
如果是要取消單個(gè)任務(wù),可以使用TimerTask的cancel()方法。
當(dāng)TimerTask調(diào)用cancel之后,任務(wù)是取消了,但Timer自身并不能馬上知道TimerTask被取消,而是在準(zhǔn)備執(zhí)行前才知道,因此Timer內(nèi)部還維護(hù)著這個(gè)任務(wù)的引用。若希望Timer立即清除引用,可調(diào)用Timer.purge()立即執(zhí)行清除。
到此這篇關(guān)于Java Timer使用講解的文章就介紹到這了,更多相關(guān)Java Timer使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在java中如何將inputStream對(duì)象轉(zhuǎn)換為File對(duì)象(不生成本地文件)
這篇文章主要介紹了在java中如何將inputStream對(duì)象轉(zhuǎn)換為File對(duì)象(不生成本地文件),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
Spring?Boot項(xiàng)目獲取resources目錄下文件并返回給前端的方案
我們?cè)陧?xiàng)目中經(jīng)常碰到需要讀取固定文件的場(chǎng)景,如模板文件,一般做法是將文件放在resources目錄下,程序通過(guò)多種方式可以順利讀取文件,這篇文章主要給大家介紹了關(guān)于Spring?Boot項(xiàng)目獲取resources目錄下文件并返回給前端的相關(guān)資料,需要的朋友可以參考下2024-07-07
SpringBoot3實(shí)現(xiàn)國(guó)際化的代碼步驟
國(guó)際化,簡(jiǎn)稱(chēng) i18n,源自國(guó)際化英文單詞 internationalization 中首字母 i 與尾字母 n 之間有 18 個(gè)字母,本文給大家介紹了SpringBoot3實(shí)現(xiàn)國(guó)際化的操作步驟,并通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下2024-12-12
Kotlin與Java 泛型缺陷和應(yīng)用場(chǎng)景詳解
這篇文章主要為大家介紹了Kotlin與Java 泛型缺陷和應(yīng)用場(chǎng)景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
springboot整合log4j的踩坑實(shí)戰(zhàn)記錄
log日志的重要性不言而喻,所以我們需要在系統(tǒng)內(nèi)根據(jù)實(shí)際的業(yè)務(wù)進(jìn)行日志的整合,下面這篇文章主要給大家介紹了關(guān)于springboot整合log4j的踩坑實(shí)戰(zhàn)記錄,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04
如何利用Java輸出鏈表中倒數(shù)第k個(gè)結(jié)點(diǎn)
這篇文章主要給大家介紹了關(guān)于如何利用Java輸出鏈表中倒數(shù)第k個(gè)結(jié)點(diǎn)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-12-12
springboot項(xiàng)目開(kāi)啟https協(xié)議的項(xiàng)目實(shí)現(xiàn)
本文主要介紹了springboot項(xiàng)目開(kāi)啟https協(xié)議的項(xiàng)目實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
Java窗體動(dòng)態(tài)加載磁盤(pán)文件的實(shí)現(xiàn)方法
這篇文章主要介紹了Java窗體動(dòng)態(tài)加載磁盤(pán)文件的實(shí)現(xiàn)方法,需要的朋友可以參考下2014-03-03
深入淺出講解Java比較器及數(shù)學(xué)常用類(lèi)
這篇文章主要介紹了深入淺出講解Java比較器及數(shù)學(xué)常用類(lèi),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
Java?數(shù)據(jù)結(jié)構(gòu)深入理解ArrayList與順序表
ArrayList?類(lèi)是一個(gè)可以動(dòng)態(tài)修改的數(shù)組,與普通數(shù)組的區(qū)別就是它是沒(méi)有固定大小的限制,我們可以添加或刪除元素。ArrayList?繼承了?AbstractList?,并實(shí)現(xiàn)了?List?接口,順序表是將元素順序地存放在一塊連續(xù)的存儲(chǔ)區(qū)里,元素間的順序關(guān)系由它們的存儲(chǔ)順序自然表示2022-04-04

