Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/225.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何访问线程lambda中的非final变量?_Java_Android_Multithreading_Lambda_Final - Fatal编程技术网

Java 如何访问线程lambda中的非final变量?

Java 如何访问线程lambda中的非final变量?,java,android,multithreading,lambda,final,Java,Android,Multithreading,Lambda,Final,我需要在线程lambda中修改一个自定义对象,因为我需要执行一个操作并为其赋值 问题是,当我在Thread()中声明变量时,它不能从封闭函数返回。然后,如果我尝试将其设置为全局变量,并在线程内部为其分配一些值,则无法实现,因为lambdas只允许在它们内部使用final或final变量 对此,什么是解决方法/解决方案 // Gives an undesired result public class MeClass { public static Response response

我需要在线程lambda中修改一个自定义对象,因为我需要执行一个操作并为其赋值

问题是,当我在Thread()中声明变量时,它不能从封闭函数返回。然后,如果我尝试将其设置为全局变量,并在线程内部为其分配一些值,则无法实现,因为lambdas只允许在它们内部使用final或final变量

对此,什么是解决方法/解决方案

 // Gives an undesired result 
 public class MeClass {
    public static Response response = new Response();

    // TODO: Make response specific to a method and not global

    public Response get(String endpoint) {
        new Thread(() -> {
            try {
                this.response = OffredUtil.makeGetRequest(endpoint);
            } catch (Exception e) {
                this.response.isException = true;
                Log.d(TAG, e.getMessage());
            }
        }).start();
        return this.response;
    }
    // Another method with similar function accessing response

}
所以我想在方法本身内部声明
响应
,但是我不能这样做,因为只有最终变量可用

// Gives an error
public Response get(String endpoint) {
        Response response = new Response();
        new Thread(() -> {
            try {
                response = OffredUtil.makeGetRequest(endpoint);
            } catch (Exception e) {
                this.response.isException = true;
                Log.d(TAG, e.getMessage());
            }
        }).start();
        return response;

假设这是允许的?你希望它会回来什么

// Warning! This is an example of what *NOT* to do.
//
public Response get(String endpoint) {
    Response response = new Response();
    new Thread(() -> {
        response = OffredUtil.makeGetRequest(endpoint);
    }).start();
    return response;
}
没有理由认为
response=OffredUtil.makeGetRequest(端点)语句将一直执行到
返回响应之前语句。事实上,它可能要过一段时间才会执行

你真正想要的是

  • 让您的
    get(endpoint)
    方法返回可变对象,以及
  • 调用方等待新值被其他线程存储到可变对象中的一种方法
Java标准库为这种可变对象定义了一个接口:称为。
Future
有一个
get()
方法,如果需要,它将等待其他线程通过给它一个值来完成Future,然后
get()
将返回该值

最简单的使用方法是通过类:


即使代码可以编译,它仍然不能工作,因为
返回响应语句在
响应=…]之前执行线程的语句。重新思考您正在尝试做什么,例如,为什么您要创建一个线程在后台运行代码,但仍然希望结果立即可用?这毫无意义,是吗?如果你愿意等待完成,那么启动一个新线程有什么意义?Re,“…Android…UI可能会冻结…”唯一“冻结”UI的是,如果UI线程中调用的某个函数花费太多时间。如果对
makeGetRequest(endpoint)
的直接调用冻结了UI,那么这意味着需要花费太多时间。您无法通过请求其他线程调用它然后等待结果来修复此问题。这只会花费更多的时间。你必须找到一些方法让你的UI显示你现在已经开始了
makeGetRequest(…)
调用,然后当结果出来时,再次更新UI以显示它。我投票结束这个问题,因为它是一个问题。OP没有告诉我们真正的问题是什么,而是要求我们帮助实现一个糟糕的解决方案。我可以在类本身中创建一个方法,执行
public Future get(String endpoint){return CompletableFuture.supplyAsync(()->{return OffredUtil.makeGetRequest(endpoint);}}
获取响应并返回该响应。反过来,我将从实际调用方调用这个新方法,并获取响应,而不需要在实际调用方中使用
Future
对象?@nietzsche,我不明白你为什么要这样做。如果调用方在等待
OffredUtil.makeGetRequest(endpoint)
的结果时从不做任何其他事情,那么在不同的线程中这样做又有什么意义呢?为什么不直接调用这个函数呢?我基本上只希望实际的调用方访问我的类,而不必显式地使用
java.util.concurrent
对象,比如
Future
。尼采,“工作”是什么意思?你的意思是,Java编译器会让你这么做吗?是的,编译器会让你这么做。你是说,打电话的人会得到预期的结果吗?是的,调用者将得到预期的结果。你的意思是,调用者会及时得到预期的结果以防止你的Android用户界面冻结吗?那就不行了,这根本没用。
import java.util.concurrent.Future;
import java.util.concurrent.CompletableFuture;
...
public Future<Response> get(String endpoint) {
    return CompletableFuture.supplyAsync(() -> {
       return OffredUtil.makeGetRequest(endpoint);
    });
}
...
Future<Response> fr = myClassInstance.get(endpoint);
doSomethingElseConcurrentlyWithThe_makeGetRequest_call(...);
try {
    Response r = fr.get();
    ...
} catch (Exception e) {
    o.response.isException = true;
    Log.d(TAG, e.getMessage());
}