如何在 Java 中正确执行线程回调?

How to properly do a thread callback in Java?

我正在 Java(没有 Android)做一个项目。我有一个线程做一些长时间的工作,我希望在工作完成时调用主线程中的一个函数。我已经看到很多问题都在谈论这个问题,但似乎没有答案有效。我当前的实现如下所示:

这是行不通的,因为当线程结束时,它总是打印新线程的名称,而不是主线程。如何让回调函数在主线程上被调用,而在新线程而不是上被调用?

谢谢!

编辑: 这是我试过的代码:

import java.util.Random;

public class ATestThreadClass {
    public static void main(String[] args) {
        new Thread(new RandomRunnable(data -> {
        System.out.println("Called on " + Thread.currentThread().getName());
        System.out.println(data.toString());
    })).start();
}

    static class RandomRunnable implements Runnable {
    private final CallbackInterface callbackInterface;

    public RandomRunnable(CallbackInterface callbackInterface) {
        this.callbackInterface = callbackInterface;
    }

    @Override
    public void run() {
        // Do some very long work...
        Random random = new Random();
        RandomCallbackData data = new RandomCallbackData();
        data.a = random.nextInt(100);
        data.b = random.getClass().getSimpleName();
        data.c = random.nextLong();
        callbackInterface.callback(data); // THIS REALLY NEEDS TO BE CALLED ON THE MAIN THREAD
    }
}


interface CallbackInterface {
    void callback(RandomCallbackData data);
}

static class RandomCallbackData {
    public int a;
    public String b;
    public long c;

    @Override
    public String toString() {
        return "RandomCallbackData{" +
                "a=" + a +
                ", b='" + b + '\'' +
                ", c=" + c +
                '}';
        }
    }
}

(抱歉奇怪的格式;当我粘贴代码时堆栈溢出搞砸了)

下面是日志:

Called on Thread-3
RandomCallbackData{a=77, b='Random', c=-7871432476136355770}

Process finished with exit code 0

以下可能不是最佳答案,如有更好的请指正。这是我的代码:

Main Class:
https://pastebin.com/hSZjGWsr

Holder class for tasks:
https://pastebin.com/eme9nqtA

Callback code:
https://pastebin.com/JvXadT0L

Worker thread code:
https://pastebin.com/fZYdfn9m

其中很多内容都可以在 java 中完成,但全部手写更容易理解。

以下是其工作原理的摘要:

  • 有一个工作线程class。当您调用方法 .get() 时,线程 return 是最终值。您还可以调用 .isDone() 来确定线程是否已完成。
  • 一个列表存储一个 holder class,它跟踪工作线程及其回调。方法 update 应该在循环中调用。
  • 当一个线程完成时,相应的回调将被调用,其 return 值。然后线程停止,任务从列表中删除。
  • 您可以定义检查任务竞争的频率。如果您的应用程序需要立即调用回调,请传入 0 或 1 作为构造函数中的第一个参数。否则,请传入您希望以毫秒为单位更新的速度。
  • 当您不再使用该系统时,您应该调用方法markComplete

有关其工作原理的更多信息,请参阅我在代码中添加的注释。

我知道我的实现需要一个循环,这意味着它不是最佳选择。这是我能想到的唯一方法。再次提醒,有更好的方法请指正

希望对您有所帮助! ;)