如何在 Java 中正确执行线程回调?
How to properly do a thread callback in Java?
我正在 Java(没有 Android)做一个项目。我有一个线程做一些长时间的工作,我希望在工作完成时调用主线程中的一个函数。我已经看到很多问题都在谈论这个问题,但似乎没有答案有效。我当前的实现如下所示:
- 有一个带有回调函数的接口
- 将该接口作为runnable中的参数
- 在main中实现class,然后创建runnable并启动一个新线程。
- 在回调函数中,打印当前线程名称
这是行不通的,因为当线程结束时,它总是打印新线程的名称,而不是主线程。如何让回调函数在主线程上被调用,而在新线程而不是上被调用?
谢谢!
编辑: 这是我试过的代码:
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
。
有关其工作原理的更多信息,请参阅我在代码中添加的注释。
我知道我的实现需要一个循环,这意味着它不是最佳选择。这是我能想到的唯一方法。再次提醒,有更好的方法请指正
希望对您有所帮助! ;)
我正在 Java(没有 Android)做一个项目。我有一个线程做一些长时间的工作,我希望在工作完成时调用主线程中的一个函数。我已经看到很多问题都在谈论这个问题,但似乎没有答案有效。我当前的实现如下所示:
- 有一个带有回调函数的接口
- 将该接口作为runnable中的参数
- 在main中实现class,然后创建runnable并启动一个新线程。
- 在回调函数中,打印当前线程名称
这是行不通的,因为当线程结束时,它总是打印新线程的名称,而不是主线程。如何让回调函数在主线程上被调用,而在新线程而不是上被调用?
谢谢!
编辑: 这是我试过的代码:
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
。
有关其工作原理的更多信息,请参阅我在代码中添加的注释。
我知道我的实现需要一个循环,这意味着它不是最佳选择。这是我能想到的唯一方法。再次提醒,有更好的方法请指正
希望对您有所帮助! ;)