精华内容
下载资源
问答
  • java监听机制的原理-回调机制
    2021-03-08 19:47:45

    public interface TextListener {

    public void excute();

    }

    可以看到,接口中并没有excute()方法的具体实现。

    接下来创建一个类:Text,这个类中包含了几个东西:第一个,TextListener的集合,因为可以为Text添加多个TextListener监听,因此,用一个集合来保存所有的监听;第二个addTextListener(TextListener

    tl),这个方法是给Text注册监听的,说的通俗一点,就是把一个新的监听添加到TextListener集合中去;第三个方法removeListener(TextListener

    tl),顾名思义,就是把某个监听从监听集合中移除,第三个方法叫excute(),这里不要和TextListener中的excute()方法混淆了,这个方法的作用就是回调注册了的TextListener,执行其中的代码。

    import java.util.List;

    import java.util.Vector;

    public class Text {

    private List listeners = new Vector<>();

    public Text() {

    }

    public void addTextListener(TextListener listener) {

    listeners.add(listener);

    }

    public void removeTextListener(TextListener listener) {

    listeners.remove(listener);

    }

    public void excute() {

    for (TextListener t : listeners) {

    t.excute();

    }

    }

    }

    注:Text中的excute()方法,实际上就是遍历监听集合中的所有元素,依次调用TextListener的excute()方法。额。。。希望没有把这两个excute方法混淆了,命名可以随便改。

    然后,写一个main函数,来运行着写代码:

    public static void main(String[] args) {

    Text text = new Text();

    text.addTextListener(new TextListener() {

    @Override

    public void excute() {

    System.out.println("cc is better man");

    }

    });

    text.addTextListener(new TextListener() {

    @Override

    public void excute() {

    int size = 100;

    int rst = 0;

    for (int i = 0; i < size; i++) {

    rst += i;

    }

    System.out.println("the sum of 0 to 100 is :" + rst);

    }

    });

    text.excute();

    }

    说明:首先创建了一个Text对象,再为Text对象添加了两个TextListener的监听,每个监听里面实现的excute()方法不一样,最后,再调用text.excute()方法,就会依次执行注册了的监听。在这个地方,由于text中,监听集合实际上是一个接口的集合,Text并不知道调用接口的excute()方法后,会执行什么代码,在注册的时候,接口的excute()方法的实现,也不会执行,所以,为text添加监听的时候,text也不知道自己在执行excute()方法的时候,输出结果是什么。

    对于这种基于注册机制,来调用接口方法的用法,就是回调机制。

    按道理来讲,在添加监听的时候,是实现了一个接口的,也就是说,在这个时候,创建了一个接口的实例,并且将这个实例放在内存中了,text的addTextListener方法,实际上存了一个这个接口实例的一个引用地址。当执行text.excute()方法的时候,会根据注册的TextListener的内存地址,来找到这个监听接口的实例,然后再调用TextListener的excute方法。

    其实,上述代码还有一种写法,那就是创建一个类,实现TextListener接口的excute()方法,然后,new一个这个类,把这个类注册到text的监听里面,也能够实现同样的效果。

    代码如下:

    public class TextListenerImpl

    implements TextListener {

    @Override

    public void excute() {

    System.out.println("回调了这个方法~~~~~");

    }

    }

    text.addTextListener(new

    TextListenerImpl());//此为注册方法

    其实这样子看的话,会比较清晰,当然,这个TextListener的实现类中的excute方法具体要执行什么,text依然不知道。

    不知道这样子有没有说清楚。先这样吧。

    更多相关内容
  • 主要介绍了Java使用自定义注解实现为事件源绑定事件监听器操作,结合实例形式分析了java自定义注解、注解处理、事件监听与响应等相关操作技巧,需要的朋友可以参考下
  • NULL 博文链接:https://nannan408.iteye.com/blog/2023486
  • 面试过程中经常会被面试官问到为什么我们调用start()方法时会执行run()方法,为什么不能直接调用run()方法,问的一头雾水,今天小编给大家介绍下Java线程的start方法回调run方法的操作技巧,需要的朋友参考下吧
  • 说明: http://blog.csdn.net/yangzhaomuma/article/details/50967851
  • 由Kafka事件监听回顾Java回调

    千次阅读 2019-02-27 12:47:33
    Kafka触发监听原理及代码 监听器 public interface ProducerListener&lt;K, V&gt; { /** * Invoked after the successful send of a message (that is, after it has been acknowledged by the broker...

    Kafka触发监听原理及代码

    监听器

    public interface ProducerListener<K, V> {
    
       /**
        * Invoked after the successful send of a message (that is, after it has been acknowledged by the broker).
        * @param producerRecord the actual sent record
        * @param recordMetadata the result of the successful send operation
        */
       default void onSuccess(ProducerRecord<K, V> producerRecord, RecordMetadata recordMetadata) {
          onSuccess(producerRecord.topic(), producerRecord.partition(),
                producerRecord.key(), producerRecord.value(), recordMetadata);
       }
    
       /**
        * Invoked after the successful send of a message (that is, after it has been acknowledged by the broker).
        * If the method receiving the ProducerRecord is overridden, this method won't be called
        * @param topic the destination topic
        * @param partition the destination partition (could be null)
        * @param key the key of the outbound message
        * @param value the payload of the outbound message
        * @param recordMetadata the result of the successful send operation
        */
       default void onSuccess(String topic, Integer partition, K key, V value, RecordMetadata recordMetadata) {
       }
    
       /**
        * Invoked after an attempt to send a message has failed.
        * @param producerRecord the failed record
        * @param exception the exception thrown
        */
       default void onError(ProducerRecord<K, V> producerRecord, Exception exception) {
          onError(producerRecord.topic(), producerRecord.partition(),
                producerRecord.key(), producerRecord.value(), exception);
       }
    
       /**
        * Invoked after an attempt to send a message has failed.
        * If the method receiving the ProducerRecord is overridden, this method won't be called
        * @param topic the destination topic
        * @param partition the destination partition (could be null)
        * @param key the key of the outbound message
        * @param value the payload of the outbound message
        * @param exception the exception thrown
        */
       default void onError(String topic, Integer partition, K key, V value, Exception exception) {
       }
    
       /**
        * Return true if this listener is interested in success as well as failure.
        * @deprecated the result of this method will be ignored.
        * @return true to express interest in successful sends.
        */
       @Deprecated
       default boolean isInterestedInSuccess() {
          return false;
       }
    
    }

    触发回调

    KafkaTemplate类中使用send时触发回调

    使用者只需要实现监听接口即可

    以下参考自:https://my.oschina.net/u/923324/blog/792857

    回调函数

    为什么首先会讲回调函数呢?因为这个是理解监听器、观察者模式的关键。

    什么是回调函数

    所谓的回调,用于回调的函数。 回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数。 有这么一句通俗的定义:就是程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。程序员B要让a调用自己的程序b中的一个方法,于是,他通过a中的接口回调自己b中的方法。

    举个例子:

    这里有两个实体:回调抽象接口、回调者(即程序a)

    • 回调接口(ICallBack )
    public interface ICallBack {
        public void callBack();
    }
    
    • 回调者(用于调用回调函数的类)
    public class Caller {
        
        public void call(ICallBack callBack){
            System.out.println("start...");
            callBack.callBack();
            System.out.println("end...");
        }
        
    }
    
    • 回调测试:
     public static void main(String[] args) {
           Caller call = new Caller();
           call.call(new ICallBack(){
    
            @Override
            public void callBack() {
                System.out.println("终于回调成功了!");
                
            } 
           });
    
        }
    

    控制台输出:

    start...

    终于回调成功了!

    end...

    还有一种写法

           ICallBack callBackB = new ICallBack(){
            @Override
            public void callBack() {
                System.out.println("终于回调成功了!");
            }           
           };
           call.call(callBackB);
    

    或实现这个ICallBack接口类

    class CallBackC implements ICallBack{
            @Override
            public void callBack() {
                System.out.println("终于回调成功了!");  
            }
           }
    

    有没有发现这个模型和执行一个线程,Thread很像。 没错,Thread就是回调者,Runnable就是一个回调接口。

    new Thread(new Runnable(){
            @Override
            public void run() {
                 System.out.println("回调一个新线程!");  
            }}).start();
    

    Callable也是一个回调接口,原来一直在用。 接下来我们开始讲事件监听器

    事件监听模式

    什么是事件监听器

    监听器将监听自己感兴趣的事件一旦该事件被触发或改变,立即得到通知,做出响应。例如:android程序中的Button事件。

    java的事件监听机制可概括为3点:

    1. java的事件监听机制涉及到 事件源,事件监听器,事件对象 三个组件,监听器一般是接口,用来约定调用方式
    2. 当事件源对象上发生操作时,它将会调用事件监听器的一个方法,并在调用该方法时传递事件对象过去
    3. 事件监听器实现类,通常是由开发人员编写,开发人员通过事件对象拿到事件源,从而对事件源上的操作进行处理

    举个例子

    这里我为了方便,直接使用jdk,EventListener 监听器,感兴趣的可以去研究下源码,非常简单。

    监听器接口

    public interface EventListener extends java.util.EventListener {
        //事件处理
        public void handleEvent(EventObject event);
    }
    
    

    事件对象

    public class EventObject extends java.util.EventObject{
        private static final long serialVersionUID = 1L;
        public EventObject(Object source){
            super(source);
        }
        public void doEvent(){
            System.out.println("通知一个事件源 source :"+ this.getSource());
        }
    
    }
    

    事件源

    事件源是事件对象的入口,包含监听器的注册、撤销、通知

    
    public class EventSource {
       //监听器列表,监听器的注册则加入此列表
        private Vector<EventListener> ListenerList = new Vector<EventListener>();
        //注册监听器
        public void addListener(EventListener eventListener){
            ListenerList.add(eventListener);
        }
        //撤销注册
        public void removeListener(EventListener eventListener){
            ListenerList.remove(eventListener);
        }
     //接受外部事件
        public void notifyListenerEvents(EventObject event){        
            for(EventListener eventListener:ListenerList){
                    eventListener.handleEvent(event);
            }
        }
        
    }
    
    

    测试执行

    public static void main(String[] args) {
            EventSource eventSource = new EventSource();
            
            eventSource.addListener(new EventListener(){
                @Override
                public void handleEvent(EventObject event) {
                    event.doEvent();
                    if(event.getSource().equals("closeWindows")){
                        System.out.println("doClose");
                    } 
                }
                
            });
    
    
            /*
             * 传入openWindows事件,通知listener,事件监听器,
             对open事件感兴趣的listener将会执行
             **/
            eventSource.notifyListenerEvents(new EventObject("openWindows"));
            
    }
    

    控制台显示:

    通知一个事件源 source :openWindows

    通知一个事件源 source :openWindows

    doOpen something...

    到这里你应该非常清楚的了解,什么是事件监听器模式了吧。 那么哪里是回调接口,哪里是回调者,对!EventListener是一个回调接口类,handleEvent是一个回调函数接口,通过回调模型,EventSource 事件源便可回调具体监听器动作。

    有了了解后,这里还可以做一些变动。 对特定的事件提供特定的关注方法和事件触发

    
    public class EventSource {
         ...
    public void onCloseWindows(EventListener eventListener){
            System.out.println("关注关闭窗口事件");
            ListenerList.add(eventListener);
        }
        
        public void doCloseWindows(){
            this.notifyListenerEvents(new EventObject("closeWindows"));
        }
        ...
    }
    
    public static void main(String[] args) {
     EventSource windows = new EventSource();
            /**
             * 另一种实现方式
             */
            //关注关闭事件,实现回调接口
            windows.onCloseWindows(new EventListener(){
    
                @Override
                public void handleEvent(EventObject event) {
                    event.doEvent();
                    if(event.getSource().equals("closeWindows")){
                        System.out.println("通过onCloseWindows来关注关闭窗口事件:并执行成功。 closeWindows");
                    }
                    
                }
                
            });
            
           //窗口关闭动作
            windows.doCloseWindows();
    
    }
    

    这种就类似于,我们的窗口程序,Button监听器了。我们还可以为单击、双击事件定制监听器。

    观察者模式

    什么是观察者模式

    观察者模式其实原理和监听器是一样的,使用的关键在搞清楚什么是观察者、什么是被观察者。

    • 观察者(Observer)相当于事件监器。有个微博模型比较好理解,A用户关注B用户,则A是B的观察者,B是一个被观察者,一旦B发表任何言论,A便可以获得。
    • 被观察者(Observable)相当于事件源和事件,执行事件源通知逻辑时,将会回调observer的回调方法update。

    举个例子

    为了方便,同样我直接使用jdk自带的Observer。

    一个观察者

    public class WatcherDemo implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            if(arg.toString().equals("openWindows")){
                System.out.println("已经打开窗口");
            }
        }
    }
    

    被观察者

    Observable 是jdk自带的被观察者,具体可以自行看源码和之前的监听器事件源类似。

    主要方法有

    • addObserver() 添加观察者,与监听器模式类似
    • notifyObservers() 通知所有观察者

    类Watched.java的实现描述:被观察者,相当于事件监听的事件源和事件对象。又理解为订阅的对象 主要职责:注册/撤销观察者(监听器),接收主题对象(事件对象)传递给观察者(监听器),具体由感兴趣的观察者(监听器)执行

    /**
     * 
     * 类Watched.java的实现描述:被观察者,相当于事件监听的事件源和事件对象。又理解为订阅的对象
     * 主要职责:注册/撤销观察者(监听器),接收主题对象(事件对象)传递给观察者(监听器),具体由感兴趣的观察者(监听器)执行
     * @author xuan.lx 2016年11月22日 下午3:52:11
     */
    public class Watched extends Observable {
    
        public void notifyObservers(Object arg) {
            
            /**
             * 为避免并发冲突,设置了changed标志位changed =true,则当前线程可以通知所有观察者,内部同步块会完了会设置为false;
           通知过程中,正在新注册的和撤销的无法通知到。
             */
            super.setChanged();
            /**
             * 事件触发,通知所有感兴趣的观察者
             */
            super.notifyObservers(arg);
           
        }
        
    }
    

    测试执行

        public static void main(String[] args) {
            Watched watched = new Watched();
            WatcherDemo watcherDemo = new WatcherDemo();
            watched.addObserver(watcherDemo);
            watched.addObserver(new Observer(){
                @Override
                public void update(Observable o, Object arg) {
                    if(arg.toString().equals("closeWindows")){
                        System.out.println("已经关闭窗口");
                    }
                }
            });
            //触发打开窗口事件,通知观察者
            watched.notifyObservers("openWindows");
            //触发关闭窗口事件,通知观察者
            watched.notifyObservers("closeWindows");
    
        }
    

    控制台输出:

    已经打开窗口

    已经关闭窗口

    总结

    从整个实现和调用过程来看,观察者和监听器模式基本一样。

    有兴趣的你可以基于这个模型,实现一个简单微博加关注和取消的功能。 说到底,就是事件驱动模型,将调用者和被调用者通过一个链表、回调函数来解耦掉,相互独立。

    “你别来找我,有了我会找你”。

    整个设计模式的初衷也就是要做到低耦合,低依赖。

    再延伸下,消息中间件是什么一个模型? 将生产者+服务中心(事件源)和消费者(监听器)通过消息队列解耦掉. 消息这相当于具体的事件对象,只是存储在一个队列里(有消峰填谷的作用),服务中心回调消费者接口通过拉或取的模型响应。 想必基于这个模型,实现一个简单的消息中间件也是可以的。

    还比如gava ListenableFuture,采用监听器模式就解决了future.get()一直阻塞等待返回结果的问题。

    有兴趣的同学,可以再思考下观察者和责任链之间的关系, 我是这样看的。

    同样会存在一个链表,被观察者会通知所有观察者,观察者自行处理,观察者之间互不影响。 而责任链,讲究的是击鼓传花,也就是每一个节点只需记录继任节点,由当前节点决定是否往下传。 常用于工作流,过滤器web filter。

    展开全文
  • 执行结果如下: 工具优化-监听过期、增加回调 我们在使用TimedCache会发现,一旦缓存过期我们并不能立马知道,很多工作场景中需要对缓存做监听回调。所以我升级了一下该工具类。 import cn.hutool.cache.CacheUtil; ...

    目录

    简述

    Maven依赖

    简单使用

    工具优化-监听过期、增加回调

    总结


    简述

    我们在工作中会碰到需要使用带过期时间的缓存场景。但是使用redis有太重了,毕竟缓存的数据很小,放在内存够够的。hutools提供了TimedCache时间缓存工具,可以实现该场景。下面使用到该组件,并为了适配工作场景,对该工具类做优化升级。

    Maven依赖

            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.4.6</version>
            </dependency>
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>30.1.1-jre</version>
            </dependency>

    简单使用

    不多说了,上代码。

    import cn.hutool.cache.CacheUtil;
    import cn.hutool.cache.impl.TimedCache;
    import cn.hutool.core.thread.ThreadUtil;
    
    /** @Author huyi @Date 2021/10/12 17:00 @Description: */
    public class TimedCacheUtils {
      private static final TimedCache<String, String> TIMED_CACHE = CacheUtil.newTimedCache(5000);
    
      static {
        /** 每5ms检查一次过期 */
        TIMED_CACHE.schedulePrune(5);
      }
    
      /**
       * 存入键值对,提供消逝时间
       *
       * @param key
       * @param value
       * @param timeout
       */
      public static void put(String key, String value, Long timeout) {
        /** 设置消逝时间 */
        TIMED_CACHE.put(key, value, timeout);
      }
    
      /**
       * 每次重新get一次缓存,均会重新刷新消逝时间
       * @param key
       * @return
       */
      public static String get(String key) {
        return TIMED_CACHE.get(key);
      }
    
      public static void main(String[] args) {
        put("haha", "1", 3000L);
        ThreadUtil.sleep(2000);
        //    if (TIMED_CACHE.containsKey("haha")) {
        //      System.out.println("aa");
        //    }
        System.out.println("第1次结果:" + get("haha"));
        ThreadUtil.sleep(2000);
        System.out.println("第2次结果:" + get("haha"));
        ThreadUtil.sleep(5000);
        System.out.println("第3次结果:" + get("haha"));
        // 取消定时清理
        TIMED_CACHE.cancelPruneSchedule();
      }
    }

    首先我们看一下执行的效果

     说明:

    1、设置的超时时间为3000毫秒,所以第一次打印在2秒钟,所以可以获取到值。

    2、因为第一次打印调用了get方法,刷新了过期时间,所以依然可以获取到值。

    3、第三次打印在5秒后,所以已经过期,无法获取到值,打印null。

    那么,需要知道是否缓存还在可以使用containsKey方法。如下:

        put("haha", "1", 3000L);
        ThreadUtil.sleep(2000);
        if (TIMED_CACHE.containsKey("haha")) {
          System.out.println("第1次结果:缓存存在");
        }
    //    System.out.println("第1次结果:" + get("haha"));
        ThreadUtil.sleep(2000);
        System.out.println("第2次结果:" + get("haha"));
        ThreadUtil.sleep(5000);
        System.out.println("第3次结果:" + get("haha"));
        // 取消定时清理
        TIMED_CACHE.cancelPruneSchedule();

     执行结果如下:

    工具优化-监听过期、增加回调

    我们在使用TimedCache会发现,一旦缓存过期我们并不能立马知道,很多工作场景中需要对缓存做监听回调。所以我升级了一下该工具类。

    import cn.hutool.cache.CacheUtil;
    import cn.hutool.cache.impl.TimedCache;
    import cn.hutool.core.thread.ThreadUtil;
    import com.google.common.util.concurrent.*;
    import org.checkerframework.checker.nullness.qual.Nullable;
    
    import java.text.MessageFormat;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.function.Consumer;
    
    /** @Author huyi @Date 2021/10/12 10:57 @Description: 时间缓存工具 */
    public class TimedCacheUtils {
      private static final TimedCache<String, String> TIMED_CACHE = CacheUtil.newTimedCache(5000);
      /** 线程池 */
      private static final ExecutorService executorService = Executors.newCachedThreadPool();
    
      private static final ListeningExecutorService listeningExecutorService =
          MoreExecutors.listeningDecorator(executorService);
      /** 回调方法映射 */
      private static ConcurrentHashMap<String, Consumer<String>> callbackMap;
    
      /**
       * 存入键值对,添加过期时间,和消费回调
       *
       * @param key
       * @param timeout
       * @param consumer
       */
      public static void put(String key, String value, Long timeout, Consumer<String> consumer) {
        TIMED_CACHE.put(key, value, timeout);
        addListen(key, consumer);
      }
    
      /**
       * 获取缓存值
       *
       * @param key
       * @return
       */
      public static String get(String key) {
        return TIMED_CACHE.get(key);
      }
    
      /**
       * 删除缓存和回调映射
       *
       * @param key
       */
      public static void remove(String key) {
        callbackMap.remove(key);
        TIMED_CACHE.remove(key);
      }
    
      /**
       * 添加监听器
       *
       * @param key
       * @param consumer
       */
      public static void addListen(String key, Consumer<String> consumer) {
        ListenableFuture<String> listenableFuture =
            listeningExecutorService.submit(
                () -> {
                  while (TIMED_CACHE.containsKey(key)) {
                    ThreadUtil.sleep(500);
                  }
                  return key;
                });
        Futures.addCallback(
            listenableFuture,
            new FutureCallback<String>() {
              @Override
              public void onSuccess(@Nullable String s) {
                consumer.accept(s);
              }
    
              @Override
              public void onFailure(Throwable throwable) {
                throwable.printStackTrace();
              }
            },
            listeningExecutorService);
      }
    
      public static void main(String[] args) {
        put("haha", "1", 3000L, x -> System.out.println(MessageFormat.format("[{0}] - 缓存消逝", x)));
        ThreadUtil.sleep(2000);
        System.out.println(get("haha"));
        ThreadUtil.sleep(2000);
        System.out.println(get("haha"));
        ThreadUtil.sleep(5000);
        System.out.println(get("haha"));
        // 关闭监听线程池
        listeningExecutorService.shutdown();
      }
    }

     执行结果:

     说明:

    1、可以看到监听到缓存过期,并进行了回调。

    总结

    具体的工具类使用场景,因项目而异,大家看着来。

    如果本文对你有帮助,请点个赞支持一下吧。

    展开全文
  • 海康威视sdk二次开发基于springboot报警回调功能,简单易懂,导入即用,在test目录下自行代码测试,亲测可用
  • /** * @Program: csdn @ClassName: AsyncListenUtil @Author: huyi @Date: 2021-10-30 11:48 @Description: * 异步线程监听回调工具 @Version: V1.0 */ public class AsyncListenUtil { public static final ...

    目录

    前言

    Maven依赖

    代码

    总结


    前言

    工作中是否遇到这样的场景?

    1、需要异步线程执行,而且需要获取到线程执行返回的结果。

    2、如果执行过程异常,可以按照自定义方式消费异常信息。

    如果只是单纯的使用Callable可以实现,本文提供更加优雅的工具类

    Maven依赖

            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.7.15</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>31.0.1-jre</version>
            </dependency>

    代码

    不废话,上代码。

    package com.huyi.csdn.tools;
    
    import cn.hutool.core.thread.ThreadUtil;
    import com.google.common.util.concurrent.*;
    import org.checkerframework.checker.nullness.qual.Nullable;
    import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    import java.util.function.Consumer;
    
    /**
     * @Program: csdn @ClassName: AsyncListenUtil @Author: huyi @Date: 2021-10-30 11:48 @Description:
     * 异步线程监听回调工具 @Version: V1.0
     */
    public class AsyncListenUtil {
      public static final ExecutorService executorService =
          Executors.newFixedThreadPool(10, new CustomizableThreadFactory("LISTEN-"));
      public static final ListeningExecutorService listeningExecutorService =
          MoreExecutors.listeningDecorator(executorService);
    
      /**
       * 提交任务
       *
       * @param work Callable需要线程执行的内容
       * @param consumer 结果消费
       * @param errorConsumer 异常消费
       * @param <T> 泛型
       */
      public static <T> void submit(
          Callable<T> work, Consumer<T> consumer, Consumer<Throwable> errorConsumer) {
        ListenableFuture<T> listenableFuture = listeningExecutorService.submit(work);
        Futures.addCallback(
            listenableFuture,
            new FutureCallback<T>() {
              @Override
              public void onSuccess(@Nullable T s) {
                consumer.accept(s);
              }
    
              @Override
              public void onFailure(Throwable throwable) {
                errorConsumer.accept(throwable);
              }
            },
            listeningExecutorService);
      }
    
      /** 摧毁线程池 */
      public static void destroy() {
        System.out.println("摧毁线程池");
        executorService.shutdown();
      }
    
      public static void main(String[] args) {
        AsyncListenUtil.submit(
            () -> {
              // todo 需要执行的内容
              ThreadUtil.sleep(10, TimeUnit.SECONDS);
              return "I finished my work";
            },
            result -> {
              // todo 结果处理
              System.out.println("listen get :" + result);
            },
            throwable -> {
              // todo 异常处理
              System.out.println(throwable.getMessage());
            });
        ThreadUtil.sleep(20, TimeUnit.SECONDS);
        destroy();
      }
    }
    

    代码说明

    1、提交方法主要参数有,需要执行的Callable,结果的Consumer,异常的Consumer。其中Callable调整成Supplier也是没什么问题。

    2、提供摧毁线程池方法。

    执行结果

    OK没什么问题。

    总结

    追求优雅是个好习惯。

    如果本工具对你有用的话,请点个赞吧,这对作者很重要,谢谢。

     

     

    展开全文
  • Java回调函数callback

    千次阅读 2022-03-29 11:28:06
    java 回调函数学习(监听器模式) 回调就是把函数指针做为参数传入 如函数A 做为参数传入函数B 由B函数决定何时 何地 调用函数A 经典形象的说明了回调函数(javascript中经常这么用) function A(){ } function B...
  • Java接口回调

    千次阅读 2020-01-03 13:48:30
    回调的含义和用途 什么是回调? 一般来说,模块之间都存在一定的调用关系,从调用方式上看,可以分为三类:同步调用、异步调用和回调。同步调用是一种阻塞式调用,即在函数A的函数体里通过书写函数B的函数名来调用...
  • 微信服务号回调模式

    2016-12-01 14:11:55
    用过的都说好用,环信的微信回调模式的完整代码
  • java异步回调历程

    千次阅读 2018-06-05 16:21:01
    java I/O的经历了BIO(Blocking IO... 本文主要研究一下java的异步回调机制, 主要针对juc包下的Future,Callable,FutureTask,更多关于java I/O历程。 业务场景 假定我们有这样一个业务场景,烧一壶开水,烧一...
  • oss文件上传(带回调)

    2020-11-26 17:27:59
    springboot + +oss + thymeleaf 实现的小demo , oss文件上传,根据oss链接生成二维码.
  • Java中的回调函数

    千次阅读 2020-06-20 22:50:32
    java回调函数,以类A调用类B方法为例 在类A中方法a调用了类B中的b方法,b方法在执行完成之后,会执行类A中的callback()方法,这个callback方法就是回调函数,表明类B的b方法执行完成。 2.同步回调 同步回调的...
  • java回调函数这样说,应该明白了吧!

    千次阅读 多人点赞 2017-03-01 21:04:37
    有哥们问我回调怎么用,回调怎么理解?怎么说好呢,只可意会不可言传呐,非也,回调在实际开发中使用频率其实是很高的,恰好我小时候也被回调函数欺负过,竟然问了,那么肯定要好好分享一下我的一些经验.网传回调的理解 ...
  • 回调监听机制详解

    千次阅读 2016-12-16 19:54:16
    回调监听实例需求:领导需要员工帮忙做一件事情,做完以后告诉他。这件事情的执行,是需要消耗时间的,领导不能在这里等待着。所以需要,在事情执行完后给领导一个反馈。 在编码实现中,耗时操作则需要回调监听。 ...
  • 一、回调函数为什么首先会讲回调函数呢?因为这个是理解监听器、观察者模式的关键。什么是回调函数所谓的回调,用于回调的函数。 回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数。 有这么一...
  • Redis监听回调

    千次阅读 2018-07-25 20:30:00
    当redis中key失效时进行回调操作 KeyExpirationEventMessageListener import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.slf4j.Logger; ...
  • 20180720 利用Java代码实现回调机制

    千次阅读 2018-07-20 13:40:09
    直接在回调方法中增加即可 (2)无法解决老师希望得到学生姓名、学生解题思路先于学生回答的答案的问题 因此我认为简单的返回某个结果确实没有必要使用回调而可以直接使用同步调用,但是如果有多种数据需要处理且...
  • 回调就是把函数指针做为参数传入 如函数A 做为参数传入函数B 由B函数决定何时 何地 调用函数A   经典形象的说明了回调函数(javascript中经常这么用) function A(){ } function B(A) { ... ... ...
  • java+mqtt 实现异步回调

    千次阅读 2020-06-02 09:09:08
    一、controller @RequestMapping(value = "/updateNetWork",method = RequestMethod.POST) @... } } 采用的是java观察者模式 用于监听一个变量发生变化后立即返回状态给前端。我这里做了三秒的延迟!!用于等待响应
  • Android事件监听器和回调方法

    千次阅读 2019-07-14 21:39:03
    监听器用于对特定事件进行监听,一旦监听到特定事件,则由监听器截获该事件,并回调自身的特定方法对事件进行处理。 在教程之前的实例中,我们使用的事件处理方式都是监听器。根据用户输入方式的不同,View 组件将...
  • 根据打印的日志可以看到每当有key过期时,会触发4次相同的监听方法。 redis是单机部署的 ![图片说明](https://img-ask.csdn.net/upload/202007/21/1595322652_503795.jpg) ![图片说明]...
  • java 事件监听 - 鼠标

    千次阅读 2021-02-28 10:09:23
    java 事件监听 - 鼠标//事件监听//鼠标事件监听//鼠标事件监听有两个实现接口//1、MouseListener 普通的鼠标操作//2、MouseMotionListener 鼠标的拖拽、移动import java.awt.*;import javax.swing.*;import java.awt...
  • Java之接口与回调

    千次阅读 2019-01-11 12:44:53
    前言  回调是一种常见的程序设计模式,利用回调技术可以处理这样的问题,事件A发生时要执行处理事件A的代码,判断何时发生事件A及何时执行处理... Java中Swing与AWT的事件监听处理模型就是使用接口与回调实现的...
  • 一个例子让你弄懂回调监听模式的用法

    万次阅读 多人点赞 2018-01-06 14:25:51
    首先还是老套路,先弄明白回调监听者模式。(回调在我上篇分享已经提到过了,不懂的可以翻阅我写的点击打开链接(一个能让你一辈子不会忘记的例子))。  监听者模式定义(这里实现的是一个简单的监听模式):...
  • 实用的Java回调实现

    千次阅读 2018-05-11 20:15:45
    摆脱if判断的固化编程,采用回调完成多业务类型下的处理,使得程序在面对新的业务类型时能更加灵活处理,适用于可扩展的业务场景。 因消息的业务类型有多个,并且考虑到项目后期类型会有扩展,所以此处以消息处理为...
  • java 监听类实现

    千次阅读 2018-05-28 16:00:16
    监听器模式:1)事件源,2)事件监听器(也就是我们的需要要实现的接口),3)事件对象(也就是我们用来装回调方法归属类实例的ArrayList集合),当事件源触发事件,监听器就可以回调事件对象的方法;更形象地说,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 107,280
精华内容 42,912
关键字:

java 监听回调

java 订阅