java 函数帮助 return 值
java help in function return value
我需要在这里接口还是其他什么?
如果是这样...我该怎么做?
因为它 return 对我来说是一个什么都没有的值,我希望它 return 对我来说是我已经为其设置值的值。谢谢
public double[] findbyidTodo(Context context , String loc) {
double[] list = new double[]{};
new Thread(new Runnable() {
@Override
public void run() {
Todo todo = TodoRoomDatabase.getInstance(context)
.todoDao()
.findTodoById(loc);
if (todo != null) {
list = new double[]{todo.getLatitude(), todo.getLongitude()};
}
}
}).start();
return list; // is return the null and not the new list
}
它发生是因为异步。
这是一个异步调用。这意味着它将开始但代码不会等待它。
Thread(new Runnable(){}
所以如果你这样做:
double[] list = new double[]{};
Thread(new Runnable(){}
return list;
Java 不会等待线程完成并且 returns 你仍然是空数组。
看看这个解决问题:
这里的基本问题是您正在尝试同步 return 异步计算的结果。这不可能。你不能 return 你还没有的东西!
那你应该怎么办?
简单的解决办法就是同步做数据库操作;即在当前线程中执行而不是使用 new Thread(...).start()
。只需将 run()
方法中的代码内联。
(您可以通过在代码中的最终 return 之前在线程上调用 join()
来获得相同的效果。但是您会无缘无故地创建和销毁线程。它是效率低下。)
但是,如果您需要异步执行数据库操作,您可以使用 CompletableFuture
(javadoc),如下所示:
public CompletableFuture<double[]> findbyidTodo(Context context , String loc) {
final CompletableFuture<double[]> future = new CompletableFuture<>();
new Thread(new Runnable() {
@Override
public void run() {
Todo todo = TodoRoomDatabase.getInstance(context)
.todoDao()
.findTodoById(loc);
if (todo != null) {
future.complete(new double[]{todo.getLatitude(), todo.getLongitude()});
} else {
future.complete(null);
}
}).start();
return future;
}
那么调用者可以这样做:
CompletableFuture<double[]> future = findbyidTodo(...);
// Do some other stuff
double[] result = future.get(); // This blocks until the future has been completed.
请注意,只有在数据库调用可能花费大量时间并且在数据库调用正在进行时调用线程实际上还有“其他事情”要做的情况下才值得这样做。如果不是...那么最好同步进行数据库操作。
最后,如果您要异步执行此操作,使用线程池或执行程序服务比为每个数据库操作创建一个新线程更有效。查看 ExecutorService
and Executors
的 javadoc。 (创建和销毁线程相对昂贵。)
我需要在这里接口还是其他什么?
如果是这样...我该怎么做? 因为它 return 对我来说是一个什么都没有的值,我希望它 return 对我来说是我已经为其设置值的值。谢谢
public double[] findbyidTodo(Context context , String loc) {
double[] list = new double[]{};
new Thread(new Runnable() {
@Override
public void run() {
Todo todo = TodoRoomDatabase.getInstance(context)
.todoDao()
.findTodoById(loc);
if (todo != null) {
list = new double[]{todo.getLatitude(), todo.getLongitude()};
}
}
}).start();
return list; // is return the null and not the new list
}
它发生是因为异步。
这是一个异步调用。这意味着它将开始但代码不会等待它。
Thread(new Runnable(){}
所以如果你这样做:
double[] list = new double[]{};
Thread(new Runnable(){}
return list;
Java 不会等待线程完成并且 returns 你仍然是空数组。
看看这个
这里的基本问题是您正在尝试同步 return 异步计算的结果。这不可能。你不能 return 你还没有的东西!
那你应该怎么办?
简单的解决办法就是同步做数据库操作;即在当前线程中执行而不是使用 new Thread(...).start()
。只需将 run()
方法中的代码内联。
(您可以通过在代码中的最终 return 之前在线程上调用 join()
来获得相同的效果。但是您会无缘无故地创建和销毁线程。它是效率低下。)
但是,如果您需要异步执行数据库操作,您可以使用 CompletableFuture
(javadoc),如下所示:
public CompletableFuture<double[]> findbyidTodo(Context context , String loc) {
final CompletableFuture<double[]> future = new CompletableFuture<>();
new Thread(new Runnable() {
@Override
public void run() {
Todo todo = TodoRoomDatabase.getInstance(context)
.todoDao()
.findTodoById(loc);
if (todo != null) {
future.complete(new double[]{todo.getLatitude(), todo.getLongitude()});
} else {
future.complete(null);
}
}).start();
return future;
}
那么调用者可以这样做:
CompletableFuture<double[]> future = findbyidTodo(...);
// Do some other stuff
double[] result = future.get(); // This blocks until the future has been completed.
请注意,只有在数据库调用可能花费大量时间并且在数据库调用正在进行时调用线程实际上还有“其他事情”要做的情况下才值得这样做。如果不是...那么最好同步进行数据库操作。
最后,如果您要异步执行此操作,使用线程池或执行程序服务比为每个数据库操作创建一个新线程更有效。查看 ExecutorService
and Executors
的 javadoc。 (创建和销毁线程相对昂贵。)