修改了原文中: Thread 的方法 stop(),改為用標志位來終止線程
package thread_rabbit_tortoise; public abstract class Animal extends Thread { volatile boolean stop = false; public int length = 30;// 比賽長度 public abstract void runing(); @Override public void run() { while (!stop&&length>0) { runing(); } } public void terminate() { stop = true; } // 在需要回調數據的地方(兩個子類需要),聲明一個接口 public static interface Calltoback { public void win(); } // 2.創建接口對象 public Calltoback calltoback; } package thread_rabbit_tortoise; public class Rabbit extends Animal { public Rabbit() { setName("兔子"); } @Override public void runing() { //兔子速度 int dis = 5; length -= dis; System.out.println("兔子跑了" + dis + "米,距離終點還有" + length + "米"); if (length <= 0) { length = 0; System.out.println("兔子獲得了勝利"); // 給回調對象賦值,讓烏龜不要再跑了 if (calltoback != null) { calltoback.win(); } } try { if ((2000 - length) % 20 == 0) { // 每20米休息一次,休息時間是1秒 sleep(1000); } else { //沒0.1秒跑5米 sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } } package thread_rabbit_tortoise; public class Tortoise extends Animal { public Tortoise() { setName("烏龜");// Thread的方法,給線程賦值名字 } // 重寫running方法,編寫烏龜的奔跑操作 @Override public void runing() { // 烏龜速度 int dis = 2; length -= dis; System.out.println("烏龜跑了" + dis + "米,距離終點還有" + length + "米"); if (length <= 0) { length = 0; System.out.println("烏龜獲得了勝利"); // 讓兔子不要在跑了 if (calltoback != null) { calltoback.win(); } } try { sleep(100); //沒0.1秒跑2米 } catch (InterruptedException e) { e.printStackTrace(); } } } package thread_rabbit_tortoise; import thread_rabbit_tortoise.Animal.Calltoback; public class LetOneStop implements Calltoback { // 動物對象 Animal an; // 獲取動物對象,可以傳入兔子或烏龜的實例 public LetOneStop(Animal an) { this.an = an; } // 讓動物的線程停止 @Override public void win() { // 線程停止 an.terminate(); } } package thread_rabbit_tortoise; public class MainClass { public static void main(String[] args) { Tortoise tortoise = new Tortoise(); Rabbit rabbit = new Rabbit(); LetOneStop letOneStop1 = new LetOneStop(tortoise); rabbit.calltoback = letOneStop1; LetOneStop letOneStop2 = new LetOneStop(rabbit); tortoise.calltoback = letOneStop2; tortoise.start(); rabbit.start(); } }
_______________________________________________________________________________________________________
深入理解Java回調函數
https://blog.csdn.net/jiayi_yao/article/details/51046526
廢話不多說,像許多網上介紹回調機制的文章一樣,我這里也以一個現實的例子開頭:假設你公司的總經理出差前需要你幫他辦件事情,這件事情你需要花些時間去做,這時候總經理肯定不能守着你做完再出差吧,於是就他告訴你他的手機號碼叫你如果事情辦完了你就打電話告訴他一聲;這是一個現實生活中常能碰到的例子,我們用呢就用代碼的方式來實現一個這個過程,看一下這個過程究竟是怎樣的。 首先在Eclipse中新建一個Java項目:CallBackDemoInJava; 然后再新建三個類:Manager(該類用來模擬總經理)、Personnel(該類用來模擬員工)、Main(主類); Manager的代碼如下: package com.test; /** * @description 該類用來模擬總經理 */ public class Manager { /** * @param personnel * 傳入一個員工類的對象 */ public Manager(Personnel personnel) { // 想讓該讓員工做什么 personnel.doSomething(this, "整理公司文件"); } /** * @description 當員工做完總經理讓他做的事后就通過該方法通知總經理 * @param result * 事情結果 */ public void phoneCall(String result) { System.out.println("事情" + result); } } Manager類是個模擬總經理的類,當該類的對象被造出來后就會通過Personnel的對象去執行Personnel中的doSomething方法告訴員工做些什么 Personnel的代碼如下: package com.test; /** * @description 該類用來模擬員工 */ public class Personnel { public void doSomething(Manager manager, String task) { // 總經理通過doSomething方法告訴員工要做什么 System.out.println("總經理要你做" + task); String result = "做完了"; // 當事情做完了我們就通過總經理公布的phoneCall方法通知總經理結果 manager.phoneCall(result); } } 總經理通過調用Personnel中的doSomething方法告訴員工該做些什么,當員工做完后就通過Manager中的phoneCall方法通知總經理結果 那么好的!萬事俱備,我們在Main中測試運行下代碼看看結果: package com.test; public class Main { public static void main(String[] args) { // 首先我們需要一個員工 Personnel personnel = new Personnel(); // 其次把這個員工指派給總經理 new Manager(personnel); } } 代碼執行結果如下: 回到我們剛才舉的那個現實中的例子:總經理出差前要你去辦件事情,這件事情通過doSomething告訴你了,事情要是辦完了就打總經理的電話phoneCall通知他一聲。這里的phoneCall我們就稱為回調方法,為什么稱之為回調呢?你問我我也不清楚哈~這你得問Sun公司了,不過我們從代碼的執行過程可以看出數據的流向大致是Manager—–>Personnel—–>Manager,這不就是一個“回調”的過程么?現在我們來總結下滿足回調的兩個基本條件: 1.Class A調用Class B中的X方法 2.ClassB中X方法執行的過程中調用Class A中的Y方法完成回調 一切看上去都很完美~以上例子代碼簡單通俗地描述了回調,但是這里我就會有這樣一個疑問:假設總經理出差前交了件事情給我去辦,不巧……副總經理也要給我件事去辦,更無恥的是……主管也發任務過來了,都要求說做完就打電話通知他們……這時我們就要定義更多類,什么總經理類啦~經理類啦~主管類啦~雜七雜八的類,但是這些雜七雜八的大爺們都要求做完事情就電話通知,每個類都會有一個類似phoneCall的方法作為回調方法,這時,我們利用面向對象的思想來看~是不是可以把這個回調方法抽象出來作為一個獨立的抽象類或接口呢?多態的思想油然而生~~~鑒於JAVA接口的好處,我們就定義一個名為CallBack的接口作為回調接口,再在該接口下定義一個名為backResult的抽象方法作為回調方法,讓那些總經理類啦~經理類啦~主管類啦~什么的都去實現該接口,這時候我們就來改造下我們的項目: CallBack代碼如下: package com.test; /** * @description 該類用來模擬總經理 */ public class Manager implements CallBack { /** * @param personnel * 傳入一個員工類的對象 */ public Manager(Personnel personnel) { // 想讓該讓員工做什么 personnel.doSomething(this, "整理公司文件"); } /** * @description 當員工做完總經理讓他做的事后就通過該方法通知總經理 * @param result * 事情結果 */ public void backResult(String result) { System.out.println("事情" + result); } } Personnel代碼改造后如下: doSomething方法不再傳入一個Manager對象而是一個CallBack接口: package com.test; /** * @description 該類用來模擬員工 */ public class Personnel { public void doSomething(CallBack callBack, String task) { // 總經理通過doSomething方法告訴員工要做什么 System.out.println("總經理要你做" + task); String result = "做完了"; // 當事情做完了我們就通過總經理公布的phoneCall方法通知總經理結果 callBack.backResult(result); } } Main代碼不變,執行結果也是一樣的。 ———————————————— 原文鏈接:https://blog.csdn.net/jiayi_yao/article/details/51046526