如何正确地做一个线程回调在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中完成,但是全部手工编写会更容易理解。

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

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

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

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

希望这对你有帮助!;)