【问题标题】:Simple Java Callback is not working简单的 Java 回调不起作用
【发布时间】:2018-04-05 12:27:29
【问题描述】:
interface CallableInterface
{
    void callBackMethod();
}

class Worker
{   
    public static ArrayList<String> names = new ArrayList<String>();
    static Timer t = new Timer();

    public void addToList(String newAdd, CallableInterface callback)
    {   
        names.add("BMW");
        names.add("DODGE");

        t.schedule(new TimerTask() {
            @Override
            public void run() {     
                names.add(newAdd);
            }
        }, 5000);

       callback.callBackMethod();
    }

    public void printList(){
        System.out.println(Worker.names);
    }
}


class Boss implements CallableInterface
{   
    Worker w1 = new Worker();

    public Boss(String carName)
    {   
        w1.addToList(carName, this);
    }
    public void callBackMethod()
    {
        w1.printList();
    }
}


public class IntroCallbacks
{ 
    public static void main(String[] args)
    {
        Boss b = new Boss("Mercedes");   
    }
}

我正在使用计时器模拟网络延迟。这个想法是等待计时器完成(在本例中为 5 秒),然后打印 arrayList。无论我对代码做什么,我总是只得到[BMW,DODGE]。

应该是 [BMW, DODGE, MERCEDES]。

我错过了什么?

【问题讨论】:

  • 您正在调用回调方法,然后,5 秒后,添加 MERCEDES。您可能希望在 run() 方法中调用回调。
  • 注意:你可以只使用Runnable而不是定义你自己的CallbackInterface

标签: java interface callback


【解决方案1】:

Worker::addToList 在安排计时器后立即调用Boss::callBackMethod。这将打印列表,该列表当前只有 2 个元素。约 4.99 秒后,最后一个元素被添加到列表中,但它已经被打印出来了。

如果您只想在添加第三个元素后打印列表,请将回调的调用移至添加该元素后:

public void addToList(String newAdd, CallableInterface callback)
{   
    names.add("BMW");
    names.add("DODGE");

    t.schedule(new TimerTask() {
        @Override
        public void run() {     
            names.add(newAdd);
            callback.callBackMethod();
        }
    }, 5000);
}

或者使用一些同步机制,比如CountDownLatch

【讨论】:

  • 谢谢迈克尔 :)
  • 这行得通,但把回调的调用放在那里对我来说感觉有点脏。这感觉像是一个跨领域的问题,我认为更简洁的方法可能是链接承诺,或者在 Java 中,CompletableFutures。
  • @DavidConrad 同意,但要向您的观众播放。看看他的代码,认真地问自己他是否可能理解你刚才所说的话。我确实建议在底部使用同步辅助工具,以防他想查看它。
  • 好吧,这就是为什么我刚刚发布了一个单独的答案来演示它。不是说你的答案不好。
  • @Michael 你是对的。我对 DavidConrad 的回答感到困惑,因为我是 Java 的初学者。但是,通过简单的谷歌搜索,我熟悉了 CountDownLatch 和 CompletableFuture,我目前正在使用它们来专业化我的代码;)
【解决方案2】:

我会在添加名称后使用CompletableFuture 链接打印。您可以使用延迟的 Executor 而不是 Timer 来引入 5 秒的延迟。

import static java.util.concurrent.TimeUnit.SECONDS;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

class Worker {
    private List<String> names = new ArrayList<String>();

    public CompletableFuture<Void> addToList(String name, Runnable callback) {
        names.add("BMW");
        names.add("DODGE");

        Executor in5seconds = CompletableFuture.delayedExecutor(5, SECONDS);

        return CompletableFuture.runAsync(() -> names.add(name), in5seconds)
            .thenRun(callback::run);
    }

    public void printList() {
        System.out.println(names);
    }
}

class Boss implements Runnable {
    private Worker worker = new Worker();
    private CompletableFuture<Void> future;

    public Boss(String carName) {
        future = worker.addToList(carName, this);
    }

    public void run() {
        worker.printList();
    }

    public CompletableFuture<Void> getFuture() {
        return future;
    }
}

public class IntroCallbacks {
    public static void main(String[] args) {
        Boss boss = new Boss("Mercedes");
        boss.getFuture().join();
    }
}

必须等到未来isDone()join()结束,否则程序将结束,后台守护线程将在任何有趣的事情(包括输出)发生之前终止。

【讨论】:

  • 不错。值得注意的是,CompletableFuture.delayedExecutor 仅出现在 Java 9 及更高版本中,因为很多人还没有进行切换。
  • @Michael 哦,好电话。我只是查看了文档并在那里找到了它。没有注意到它只是从 Java 9 开始。
  • 谢谢@DavidConrad。代码看起来更干净呵呵。我会调查的。
【解决方案3】:

此代码将解决您的问题.. :)

    import java.util.ArrayList;
    import java.util.Timer;
    import java.util.TimerTask;

    interface CallableInterface
    {
        void callBackMethod();
    }

    class Worker
    {   
        public static ArrayList<String> names = new ArrayList<String>();
        static Timer t = new Timer();

        public void addToList(String newAdd, CallableInterface callback)
        {   
            names.add("BMW");
            names.add("DODGE");

            t.schedule(new TimerTask() {
                @Override
                public void run() {     
                    names.add(newAdd);
                    callback.callBackMethod();
                }
            }, 5000);


        }

        public void printList(){
            System.out.println(Worker.names);
        }
    }


    class Boss implements CallableInterface
    {   
        Worker w1 = new Worker();

        public Boss(String carName)
        {   
            w1.addToList(carName, this);
        }
        public void callBackMethod()
        {
            w1.printList();
        }
    }

    public class Main {

        public static void main(String[] args) {
            Boss b = new Boss("Mercedes");   

        }

    }

【讨论】:

  • 为什么会这样?
猜你喜欢
  • 2013-09-22
  • 2011-12-02
  • 1970-01-01
  • 2018-01-03
  • 2014-04-01
  • 2015-10-12
  • 1970-01-01
  • 1970-01-01
  • 2011-11-30
相关资源
最近更新 更多