最近在学习过程中遇到了这个问题:如何获取算法的执行状态

  当时遇到这个问题时,整个人都不好了:算法都还没接触过,更不要说获取算法运行的状态了!

  自己想了很久还是没想出来,今天突然回想起师兄说的那个例子:在AWT编程中,一个界面有那么多按钮,程序是如何知道你点击的是哪个按钮的呢?

  我想了下从点击到反馈这个过程:首先我给这个按钮注册了监听器,每当我点击这个按钮的时候系统会自动生成一个事件,然后传给在该监听器中相应的方法。

  突然感觉获取算法运行状态和这个差不多啊!

  我又类比了一下AWT中的事件源事件事件处理器(监听器):事件源相当于算法本身、事件相当于算法执行到某一步、事件处理器——自己定义一个监听器。

 

  思路一下就明了了:给算法添加一个监听器属性,通过这个监听器给调用者一个反馈!

  步骤大概是这样的:

  1、定义一个监听器接口,有两个地方用到:在算法运行入口的那个类(如本例的MyProcess)要实现这个接口;算法内部要有监听器这个属性,以便调用监听器的回调方法。

  2、算法(事件源)要有一个addListener()这个方法,用于注册监听器。

  3、在算法运行入口的那个类中(本例为MyProcess)调用算法的addListenerthis)方法,参数为this,将自己传入算法中。此时监听器已经注册完成。

  4、剩下的事情就是算法的实现者考虑的事了:需要在哪些地方触发事件,将状态反馈给调用者。

   

  伪UML图:

 

         

  

 1 package com.tony.Listener;
 2 
 3 public interface MyListener {
 4     
 5     /**
 6      * 回调函数,在事件源中被调用
 7      * @param e 事件
 8      */
 9     public void callBack(MyEvent e);
10 }

 

 1 package com.tony.Listener;
 2 
 3 /**
 4  * 
 5  * 自定义的事件类
 6  */
 7 public class MyEvent {
 8     
 9     private String content;
10     
11     public MyEvent(){
12     }
13 
14     /**
15      * 更新信息
16      * @param content 内容
17      */
18     public void setContent(String content){
19         this.content = content;
20     }
21     
22     public String getContent(){
23         return content;
24     }
25 }

 

 1 package com.tony.Listener;
 2 
 3 public class MyAlgorithm {
 4 
 5     private MyListener listener;
 6     
 7     public MyAlgorithm(){
 8     }
 9     
10     /**
11      * 注册监听器
12      * @param listener 监听器
13      */
14     public void addListener(MyListener listener){
15         this.listener = listener;
16     }
17     
18     /**
19      * 模拟算法执行
20      */
21     public void start(){
22         MyEvent event = new MyEvent();
23         for(int i = 0;i < 1000;i++){
24             if(i%100 == 0){
25                 event.setContent("算法执行到第:"+i+" 步");
26                 listener.callBack(event);
27             }
28         }
29         event.setContent("算法执行完毕!");
30         listener.callBack(event);
31     }
32 
33 }

 

 

 1 package com.tony.Listener;
 2 
 3 /**
 4  * 
 5  * 算法执行入口
 6  */
 7 public class MyProcess implements MyListener{
 8 
 9     private MyAlgorithm algorithm;
10     
11     @Override
12     public void callBack(MyEvent e) {
13         System.out.println(e.getContent());
14     }
15 
16     public MyProcess(){
17         algorithm = new MyAlgorithm();
18         //注册监听器
19         algorithm.addListener(this);
20     }
21     
22     public void start(){
23         algorithm.start();
24     }
25     
26     public static void main(String[] args){
27         MyProcess process = new MyProcess();
28         process.start();
29     }
30     
31 }

 

   控制台打印结果:

 1 算法执行到第:0 2 算法执行到第:100 3 算法执行到第:200 4 算法执行到第:300 5 算法执行到第:400 6 算法执行到第:500 7 算法执行到第:600 8 算法执行到第:700 9 算法执行到第:80010 算法执行到第:90011 算法执行完毕!

 

 

  这种方式不仅能监听算法执行状态以外,还可以监听其它类似程序运行状态,只要相应的改一下事件源和事件:

  在特定的情况下,你要明确事件源、事件分别是什么。

  比如你在复制文件的时候想要获取完成的进度:此时的事件源为执行复制操作的这个程序,事件就是已经复制的百分比,百分比=已复制大小/总大小。

 

  这段代码的关键是使用了回调函数,回调函数在维基百科中的定义:在计算机程序设计中,回调函数,或简称回调,是指通过函数参数传递到其代码的,某一块可执行的引用。这一设计允许了底层代码调用在高层定义的子程序。

  以前虽然知道回调函数是给调用者一个反馈:但是在哪里调用的这样一个功能,没有使用过,还是对回调函数很模糊。

  自己写使用回调函数的代码和看别人的代码,感觉果然还是不一样的~