java——多线程回调函数

原文:https://blog.csdn.net/qq_34996727/article/details/80416277

修改了原文中: 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

 

 

posted @ 2020-05-12 14:53  kelelipeng  阅读(2336)  评论(0编辑  收藏  举报