夯實Java基礎系列11:深入理解Java中的回撥機制
目錄
- 模組間的呼叫
- 多執行緒中的“回撥”
- Java回撥機制實戰
- 例項一 : 同步呼叫
- 例項二:由淺入深
- 例項三:Tom做題
- 參考文章
- 微信公眾號
- Java技術江湖
- 個人公眾號:黃小斜
本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫裡檢視
https://github.com/h2pl/Java-Tutorial
喜歡的話麻煩點下Star哈
文章首發於我的個人部落格:
www.how2playlife.com
本文是微信公眾號【Java技術江湖】的《夯實Java基礎系列博文》其中一篇,本文部分內容來源於網路,為了把本文主題講得清晰透徹,也整合了很多我認為不錯的技術部落格內容,引用其中了一些比較好的部落格文章,如有侵權,請聯絡作者。
該系列博文會告訴你如何從入門到進階,一步步地學習Java基礎知識,並上手進行實戰,接著瞭解每個Java知識點背後的實現原理,更完整地瞭解整個Java技術體系,形成自己的知識框架。為了更好地總結和檢驗你的學習成果,本系列文章也會提供每個知識點對應的面試題以及參考答案。
如果對本系列文章有什麼建議,或者是有什麼疑問的話,也可以關注公眾號【Java技術江湖】聯絡作者,歡迎你參與本系列博文的創作和修訂。
@
模組間的呼叫
本部分摘自https://www.cnblogs.com/xrq730/p/6424471.html
在一個應用系統中,無論使用何種語言開發,必然存在模組之間的呼叫,呼叫的方式分為幾種:
(1)同步呼叫
同步呼叫是最基本並且最簡單的一種呼叫方式,類A的方法a()呼叫類B的方法b(),一直等待b()方法執行完畢,a()方法繼續往下走。這種呼叫方式適用於方法b()執行時間不長的情況,因為b()方法執行時間一長或者直接阻塞的話,a()方法的餘下程式碼是無法執行下去的,這樣會造成整個流程的阻塞。
(2)非同步呼叫
非同步呼叫是為了解決同步呼叫可能出現阻塞,導致整個流程卡住而產生的一種呼叫方式。類A的方法方法a()通過新起執行緒的方式呼叫類B的方法b(),程式碼接著直接往下執行,這樣無論方法b()執行時間多久,都不會阻塞住方法a()的執行。
但是這種方式,由於方法a()不等待方法b()的執行完成,在方法a()需要方法b()執行結果的情況下(視具體業務而定,有些業務比如啟非同步執行緒發個微信通知、重新整理一個快取這種就沒必要),必須通過一定的方式對方法b()的執行結果進行監聽。
在Java中,可以使用Future+Callable的方式做到這一點,具體做法可以參見我的這篇文章Java多執行緒21:多執行緒下其他元件之CyclicBarrier、Callable、Future和FutureTask。
(3)回撥
1、什麼是回撥?
一般來說,模組之間都存在一定的呼叫關係,從呼叫方式上看,可以分為三類同步呼叫、非同步呼叫和回撥。同步呼叫是一種阻塞式呼叫,即在函式A的函式體裡通過書寫函式B的函式名來呼叫之,使記憶體中對應函式B的程式碼得以執行。非同步呼叫是一種類似訊息或事件的機制解決了同步阻塞的問題,例如 A通知 B後,他們各走各的路,互不影響,不用像同步呼叫那樣, A通知 B後,非得等到 B走完後, A才繼續走 。回撥是一種雙向的呼叫模式,也就是說,被呼叫的介面被呼叫時也會呼叫對方的介面,例如A要呼叫B,B在執行完又要呼叫A。
2、回撥的用途
回撥一般用於層間協作,上層將本層函式安裝在下層,這個函式就是回撥,而下層在一定條件下觸發回撥。例如作為一個驅動,是一個底層,他在收到一個數據時,除了完成本層的處理工作外,還將進行回撥,將這個資料交給上層應用層來做進一步處理,這在分層的資料通訊中很普遍。
多執行緒中的“回撥”
Java多執行緒中可以通過callable和future或futuretask結合來獲取執行緒執行後的返回值。實現方法是通過get方法來呼叫callable的call方法獲取返回值。
其實這種方法本質上不是回撥,回撥要求的是任務完成以後被呼叫者主動回撥呼叫者的介面。而這裡是呼叫者主動使用get方法阻塞獲取返回值。
public class 多執行緒中的回撥 {
//這裡簡單地使用future和callable實現了執行緒執行完後
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
Future<String> future = executor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("call");
TimeUnit.SECONDS.sleep(1);
return "str";
}
});
//手動阻塞呼叫get通過call方法獲得返回值。
System.out.println(future.get());
//需要手動關閉,不然執行緒池的執行緒會繼續執行。
executor.shutdown();
//使用futuretask同時作為執行緒執行單元和資料請求單元。
FutureTask<Integer> futureTask = new FutureTask(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("dasds");
return new Random().nextInt();
}
});
new Thread(futureTask).start();
//阻塞獲取返回值
System.out.println(futureTask.get());
}
@Test
public void test () {
Callable callable = new Callable() {
@Override
public Object call() throws Exception {
return null;
}
};
FutureTask futureTask = new FutureTask(callable);
}
}
Java回撥機制實戰
曾經自己偶爾聽說過回撥機制,隱隱約約能夠懂一些意思,但是當讓自己寫一個簡單的示例程式時,自己就傻眼了。隨著工作經驗的增加,自己經常聽到這兒使用了回撥,那兒使用了回撥,自己是時候好好研究一下Java回撥機制了。網上關於Java回撥的文章一抓一大把,但是看完總是雲裡霧裡,不知所云,特別是看到抓取別人的程式碼走兩步時,總是現眼。於是自己決定寫一篇關於Java機制的文章,以方便大家和自己更深入的學習Java回撥機制。
首先,什麼是回撥函式,引用百度百科的解釋:回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響應[2].
不好意思,上述解釋我看了好幾遍,也沒理解其中深刻奧祕,相信一些讀者你也一樣。光說不練假把式,咱們還是以實戰理解脈絡。
例項一 : 同步呼叫
本文以底層服務BottomService和上層服務UpperService為示例,利用上層服務呼叫底層服務,整體執行過程如下:
第一步: 執行UpperService.callBottomService();
第二步: 執行BottomService.bottom();
第三步:執行UpperService.upperTaskAfterCallBottomService()
1.1 同步呼叫程式碼
同步呼叫時序圖:
[外鏈圖片轉存失敗(img-dapFATDy-1569148364574)(https://upload-images.jianshu.io/upload_images/3796264-6a5b5b898aa3930e.png?imageMogr2/auto-orient/strip|imageView2/2/w/1031/format/webp)]
同步呼叫時序圖
1.1.1 底層服務類:BottomService.java
package synchronization.demo;
/**
* Created by lance on 2017/1/19.
*/
public class BottomService {
public String bottom(String param) {
try { // 模擬底層處理耗時,上層服務需要等待
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return param +" BottomService.bottom() execute -->";
}
}
1.1.2 上層服務介面: UpperService.java
package synchronization.demo;
/**
* Created by lance on 2017/1/19.
*/
public interface UpperService {
public void upperTaskAfterCallBottomService(String upperParam);
public String callBottomService(final String param);
}
1.1.3 上層服務介面實現類:UpperServiceImpl.java
package synchronization.demo;
/**
* Created by lance on 2017/1/19.
*/
public class UpperServiceImpl implements UpperService {
private BottomService bottomService;
@Override
public void upperTaskAfterCallBottomService(String upperParam) {
System.out.println(upperParam + " upperTaskAfterCallBottomService() execute.");
}
public UpperServiceImpl(BottomService bottomService) {
this.bottomService = bottomService;
}
@Override
public String callBottomService(final String param) {
return bottomService.bottom(param + " callBottomService.bottom() execute --> ");
}
}
1.1.4 Test測試類:Test.java
package synchronization.demo;
import java.util.Date;
/**
* Created by lance on 2017/1/19.
*/
public class Test {
public static void main(String[] args) {
BottomService bottomService = new BottomService();
UpperService upperService = new UpperServiceImpl(bottomService);
System.out.println("=============== callBottomService start ==================:" + new Date());
String result = upperService.callBottomService("callBottomService start --> ");
//upperTaskAfterCallBottomService執行必須等待callBottomService()呼叫BottomService.bottom()方法返回後才能夠執行
upperService.upperTaskAfterCallBottomService(result);
System.out.println("=============== callBottomService end ====================:" + new Date());
}
}
1.1.5 輸出結果:
=============== callBottomService start ==================:Thu Jan 19 14:59:58 CST 2017
callBottomService start --> callBottomService.bottom() execute --> BottomService.bottom() execute --> upperTaskAfterCallBottomService() execute.
=============== callBottomService end ====================:Thu Jan 19 15:00:01 CST 2017
注意輸出結果:
是同步方式,Test呼叫callBottomService()等待執行結束,然後再執行下一步,即執行結束。callBottomService開始執行時間為Thu Jan 19 14:59:58 CST 2017,執行結束時間為Thu Jan 19 15:00:01 CST 2017,耗時3秒鐘,與模擬的耗時時間一致,即3000毫秒。
例項二:由淺入深
前幾天公司面試有問道java回撥的問題,因為這方面也沒有太多研究,所以回答的含糊不清,這回特意來補習一下。看了看網上的回撥解釋和例子,都那麼的繞口,得看半天才能繞回來,其實吧,回撥是個很簡單的機制。在這裡我用簡單的語言先來解釋一下:假設有兩個類,分別是A和B,在A中有一個方法a(),B中有一個方法b();在A裡面呼叫B中的方法b(),而方法b()中呼叫了方法a(),這樣子就同時實現了b()和a()兩個方法的功能。
疑惑:為啥這麼麻煩,我直接在類A中的B.b()方法下呼叫a()方法就行了唄。
解答:回撥更像是一個約定,就是如果我呼叫了b()方法,那麼就必須要回調,而不需要顯示呼叫
一、Java的回撥-淺
我們用例子來解釋:小明和小李相約一起去吃早飯,但是小李起的有點晚要先洗漱,等小李洗漱完成後,通知小明再一起去吃飯。小明就是類A,小李就是類B。一起去吃飯這個事件就是方法a(),小李去洗漱就是方法b()。
public class XiaoMing {
//小明和小李一起吃飯
public void eatFood() {
XiaoLi xl = new XiaoLi();
//A呼叫B的方法
xl.washFace();
}
public void eat() {
System.out.print("小明和小李一起去吃大龍蝦");
}
}
那麼怎麼讓小李洗漱完後在通知小明一起去吃飯呢
public class XiaoMing {
//小明和小李一起吃飯
public void eatFood() {
XiaoLi xl = new XiaoLi();
//A呼叫B的方法
xl.washFace();
eat();
}
public void eat() {
System.out.print("小明和小李一起去吃大龍蝦");
}
}
不過上面已經說過了這個不是回撥函式,所以不能這樣子,正確的方式如下
public class XiaoLi{//小李
public void washFace() {
System.out.print("小李要洗漱");
XiaoMing xm = new XiaoMing();
//B呼叫A的方法
xm.eat();//洗漱完後,一起去吃飯
}
}
這樣子就可以實現washFace()同時也能實現eat()。小李洗漱完後,再通知小明一起去吃飯,這就是回撥。
二、Java的回撥-中
可是細心的夥伴可能會發現,小李的程式碼完全寫死了,這樣子的場合可能適用和小明一起去吃飯,可是假如小李洗漱完不吃飯了,想和小王上網去,這樣子就不適用了。其實上面是虛擬碼,僅僅是幫助大家理解的,真正情況下是需要利用介面來設定回撥的。現在我們繼續用小明和小李去吃飯的例子來講講介面是如何使用的。
小明和小李相約一起去吃早飯,但是小李起的有點晚要先洗漱,等小李洗漱完成後,通知小明再一起去吃飯。小明就是類A,小李就是類B。不同的是我們新建一個吃飯的介面EatRice,介面中有個抽象方法eat()。在小明中呼叫這個介面,並實現eat();小李宣告這個介面物件,並且呼叫這個介面的抽象方法。這裡可能有點繞口,不過沒關係,看看例子就很清楚了。
EatRice介面:
public interface EatRice {
public void eat(String food);
}
小明:
public class XiaoMing implements EatRice{//小明
//小明和小李一起吃飯
public void eatFood() {
XiaoLi xl = new XiaoLi();
//A呼叫B的方法
xl.washFace("大龍蝦", this);//this指的是小明這個類實現的EatRice介面
}
@Override
public void eat(String food) {
// TODO Auto-generated method stub
System.out.println("小明和小李一起去吃" + food);
}
}
小李:
public class XiaoLi{//小李
public void washFace(String food,EatRice er) {
System.out.println("小李要洗漱");
//B呼叫了A的方法
er.eat(food);
}
}
測試Demo:
public class demo {
public static void main(String args[]) {
XiaoMing xm = new XiaoMing();
xm.eatFood();
}
}
測試結果:
這樣子就通過介面的形式實現了軟編碼。通過介面的形式我可以實現小李洗漱完後,和小王一起去上網。程式碼如下
public class XiaoWang implements EatRice{//小王
//小王和小李一起去上網
public void eatFood() {
XiaoLi xl = new XiaoLi();
//A呼叫B的方法
xl.washFace("輕舞飛揚上網", this);
}
@Override
public void eat(String bar) {
// TODO Auto-generated method stub
System.out.println("小王和小李一起去" + bar);
}
}
例項三:Tom做題
數學老師讓Tom做一道題,並且Tom做題期間數學老師不用盯著Tom,而是在玩手機,等Tom把題目做完後再把答案告訴老師。
1 數學老師需要Tom的一個引用,然後才能將題目發給Tom。
2 數學老師需要提供一個方法以便Tom做完題目以後能夠將答案告訴他。
3 Tom需要數學老師的一個引用,以便Tom把答案給這位老師,而不是隔壁的體育老師。
回撥介面,可以理解為老師介面
//回撥指的是A呼叫B來做一件事,B做完以後將結果告訴給A,這期間A可以做別的事情。
//這個介面中有一個方法,意為B做完題目後告訴A時使用的方法。
//所以我們必須提供這個介面以便讓B來回調。
//回撥介面,
public interface CallBack {
void tellAnswer(int res);
}
數學老師類
//老師類例項化回撥介面,即學生寫完題目之後通過老師的提供的方法進行回撥。
//那麼學生如何呼叫到老師的方法呢,只要在學生類的方法中傳入老師的引用即可。
//而老師需要指定學生答題,所以也要傳入學生的例項。
public class Teacher implements CallBack{
private Student student;
Teacher(Student student) {
this.student = student;
}
void askProblem (Student student, Teacher teacher) {
//main方法是主執行緒執行,為了實現非同步回撥,這裡開啟一個執行緒來操作
new Thread(new Runnable() {
@Override
public void run() {
student.resolveProblem(teacher);
}
}).start();
//老師讓學生做題以後,等待學生回答的這段時間,可以做別的事,比如玩手機.\
//而不需要同步等待,這就是回撥的好處。
//當然你可以說開啟一個執行緒讓學生做題就行了,但是這樣無法讓學生通知老師。
//需要另外的機制去實現通知過程。
// 當然,多執行緒中的future和callable也可以實現資料獲取的功能。
for (int i = 1;i < 4;i ++) {
System.out.println("等學生回答問題的時候老師玩了 " + i + "秒的手機");
}
}
@Override
public void tellAnswer(int res) {
System.out.println("the answer is " + res);
}
}
學生介面
//學生的介面,解決問題的方法中要傳入老師的引用,否則無法完成對具體例項的回撥。
//寫為介面的好處就是,很多個學生都可以實現這個介面,並且老師在提問題時可以通過
//傳入List<Student>來聚合學生,十分方便。
public interface Student {
void resolveProblem (Teacher teacher);
}
學生Tom
public class Tom implements Student{
@Override
public void resolveProblem(Teacher teacher) {
try {
//學生思考了3秒後得到了答案,通過老師提供的回撥方法告訴老師。
Thread.sleep(3000);
System.out.println("work out");
teacher.tellAnswer(111);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
測試類
public class Test {
public static void main(String[] args) {
//測試
Student tom = new Tom();
Teacher lee = new Teacher(tom);
lee.askProblem(tom, lee);
//結果
// 等學生回答問題的時候老師玩了 1秒的手機
// 等學生回答問題的時候老師玩了 2秒的手機
// 等學生回答問題的時候老師玩了 3秒的手機
// work out
// the answer is 111
}
}
參考文章
https://blog.csdn.net/fengye454545/article/details/80198446
https://blog.csdn.net/xiaanming/article/details/8703708/
https://www.cnblogs.com/prayjourney/p/9667835.html
https://blog.csdn.net/qq_25652949/article/details/86572948
https://my.oschina.net/u/3703858/blog/1798627
微信公眾號
Java技術江湖
如果大家想要實時關注我更新的文章以及分享的乾貨的話,可以關注我的公眾號【Java技術江湖】一位阿里 Java 工程師的技術小站,作者黃小斜,專注 Java 相關技術:SSM、SpringBoot、MySQL、分散式、中介軟體、叢集、Linux、網路、多執行緒,偶爾講點Docker、ELK,同時也分享技術乾貨和學習經驗,致力於Java全棧開發!
Java工程師必備學習資源: 一些Java工程師常用學習資源,關注公眾號後,後臺回覆關鍵字 “Java” 即可免費無套路獲取。
個人公眾號:黃小斜
作者是 985 碩士,螞蟻金服 JAVA 工程師,專注於 JAVA 後端技術棧:SpringBoot、MySQL、分散式、中介軟體、微服務,同時也懂點投資理財,偶爾講點演算法和計算機理論基礎,堅持學習和寫作,相信終身學習的力量!
程式設計師3T技術學習資源: 一些程式設計師學習技術的資源大禮包,關注公眾號後,後臺回覆關鍵字 “資料” 即可免費無套路獲取。
相關推薦
夯實Java基礎系列11:深入理解Java中的回撥機制
目錄 模組間的呼叫 多執行緒中的“回撥” Java回撥機制實戰 例項一 : 同步呼叫 例項二:由淺入深 例項三:Tom做題 參考文章
夯實Java基礎系列10:深入理解Java中的異常體系
目錄 為什麼要使用異常 異常基本定義 異常體系 初識異常 異常和錯誤 異常的處理方式 "不負責任"的throws 糾結的finally throw : JRE也使用的關鍵字 異常呼叫鏈 自定義異常 異常的注意事項 當finally遇上return JAVA異常常見面試題 參考文章 微信公眾號 Java技術
夯實Java基礎系列12:深入理解Java中的反射機制
本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫裡檢視 https://github.com/h2pl/Java-Tutorial 喜歡的話麻煩點下Star哈 文章首發於我的個人部落格: www.how2playlife.com 列舉(enum)型別是Java
Java基礎系列6:深入理解Java異常體系
該系列博文會告訴你如何從入門到進階,一步步地學習Java基礎知識,並上手進行實戰,接著瞭解每個Java知識點背後的實現原理,更完整地瞭解整個Java技術體系,形成自己的知識框架。 前言: Java的基本理念是“結構不佳的程式碼不能執行”。 “異常”這個詞有“我對此感到意外”的意思。問題出現了,你
夯實Java基礎系列9:深入理解Class類和Object類
目錄 Java中Class類及用法 Class類原理 如何獲得一個Class類物件 使用Class類的物件來生成目標類的例項 Object類 類構造器public Object(); registerNatives()方法; Clone()方法實現淺拷貝 getClass()方法 equals()方法
Java併發指南2:深入理解Java記憶體模型JMM
一:JMM基礎與happens-before 1併發程式設計模型的分類 1.1執行緒之間如何通訊及執行緒之間如何同步 1.11執行緒之間的通訊機制 通訊:執行緒之間以何種機制來交換資訊 通訊機制有兩種:共享記憶體和訊息傳遞。 共享記憶體併發模型 執行
java基礎學習總結(十二):深入理解java內部類
內部類 內部類也是語法糖,是因為它僅僅是一個編譯時的概念,outer.java裡面定義了一個內部類inner,一旦編譯成功,就會生成兩個完全不同的.class檔案了,分別是outer.class和outer$inner.class。所以內部類的名字完全可以和它的外部類名字相同。 內部類分為四
java基礎學習總結(九):深入理解Java泛型
一、什麼是泛型 “泛型” 意味著編寫的程式碼可以被不同型別的物件所重用。泛型的提出是為了編寫重用性更好的程式碼。泛型的本質是引數化型別,也就是說所操作的資料型別被指定為一個引數。 比如常見的集合類 LinkedList: publi
Java基礎:深入理解java異常處理機制的原理和開發應用【轉載】
Java異常處理機制在日常開發中應用頻繁,本篇文章主要在基礎的使用方法上,更進一步的,如何更加合理的使用異常機制,希望可以對各位朋友能有所幫助。 Java異常處理機制其最主要的幾個關鍵字:try、catch、finally、throw、throws,以及各種各樣
Java基礎:深入理解Java的介面和抽象類
對於面向物件程式設計來說,抽象是它的一大特徵之一。在Java中,可以通過兩種形式來體現OOP的抽象:介面和抽象類。這兩者有太多相似的地方,又有太多不同的地方。很多人在初學的時候會以為它們可以隨意互換使用,但是實際則不然。今天我們就一起來學習一下Java中的介面和
框架基礎:深入理解Java註解型別(@Annotation)
註解的概念 註解的官方定義 首先看看官方對註解的描述: An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and pa
夯實Java基礎系列4:一文了解final關鍵字的特性、使用方法,以及實現原理
目錄 final使用 final變數 final修飾基本資料型別變數和引用 final類 final關鍵字的知識點 final關鍵字的最佳實踐 final的用法 關於空白final final記憶體分配 使用final修飾方法會提高速度和效率嗎 使用final修飾變數會讓變數的值不能被改變嗎; 如何保
夯實Java基礎系列5:Java檔案和Java包結構
目錄 Java中的包概念 包的作用 package 的目錄結構 設定 CLASSPATH 系統變數 常用jar包 java軟體包的型別 dt.jar rt.jar *.java檔案的奧祕 *.Java檔案簡介 為什麼一個java原始檔中只能有一個public類? Main方法 外部類的訪問許可權
夯實Java基礎系列6:一文搞懂抽象類和介面,從基礎到面試題,揭祕其本質區別!
目錄 抽象類介紹 為什麼要用抽象類 一個抽象類小故事 一個抽象類小遊戲 介面介紹 介面與類相似點: 介面與類的區別: 介面特性 抽象類和介面的區別 介面的使用: 介面最佳實踐:設計模式中的工廠模式 介面與抽象類的本質區別是什麼? 基本語法區別 設計思想區別 如何回答面試題:介面和抽象類的區別?
夯實Java基礎系列7:一文讀懂Java 程式碼塊和執行順序
目錄 Java中的構造方法 構造方法簡介 構造方法例項 例 1 例 2 Java中的幾種構造方法詳解 普通構造方法 預設構造方法 過載構造方法 java子類構造方法呼叫父類構造方法 Java中的程式碼塊簡介 Java程式碼塊使用 區域性程式碼塊 構造程式碼塊 靜態程式碼塊 Java程式碼塊、
夯實Java基礎系列19:一文搞懂Java集合類框架,以及常見面試題
本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫裡檢視 https://github.com/h2pl/Java-Tutorial 喜歡的話麻煩點下Star哈 文章首發於我的個人部落格: www.how2playlife.com 本文參考 https://ww
夯實Java基礎系列21:Java8新特性終極指南
本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫裡檢視 https://github.com/h2pl/Java-Tutorial 喜歡的話麻煩點下Star哈 文章首發於我的個人部落格: www.how2playlife.com 這是一個Java8新增特性的總
夯實Java基礎系列22:一文讀懂Java序列化和反序列化
本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫裡檢視 https://github.com/h2pl/Java-Tutorial 喜歡的話麻煩點下Star哈 文章首發於我的個人部落格: www.how2playlife.com 本文參考 http://www
夯實Java基礎系列23:一文讀懂繼承、封裝、多型的底層實現原理
本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到我的倉庫裡檢視 https://github.com/h2pl/Java-Tutorial 喜歡的話麻煩點下Star哈 文章首發於我的個人部落格: www.how2playlife.com 從JVM結構開始談多型 Jav
轉:深入理解Java G1垃圾收集器
線程數 hot 原因 重要 特性 賦值 圖標 參數 堆內存 java垃圾收集器的歷史 第一階段,Serial(串行)收集器 在jdk1.3.1之前,java虛擬機僅僅能使用Serial收集器。 Serial收集器是一個單線程的收集器,但它的“單線程”的意義並不僅僅是說明它只