簡體   English   中英

如何訪問線程 lambda 中的非最終變量?

[英]How can I access a non-final variable in a Thread lambda?

我有一個自定義對象,我需要在 Thread lambda 中對其進行修改,因為我需要執行一個操作並為其分配一些值。

問題是當我在 Thread() 中聲明變量時,它不能從封閉函數中返回。 然后,如果我嘗試將其設為全局變量並在線程內部為其分配一些值,則無法完成,因為 lambda 僅允許在其中使用 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

}

所以我想在方法本身內部聲明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(endpoint); 語句將一直執行到return response;之前return response; 陳述。 事實上,它可能不會被直到一段時間后執行。

你真正想要的是;

  • 讓你的get(endpoint)方法返回一個可變對象,以及
  • 調用者等待新值被其他線程存儲到可變對象中的一種方式。

Java 標准庫為這種可變對象定義了一個接口:它稱為java.util.concurrent.Future Future有一個get()方法,如果需要,它將等待,直到其他線程通過給它一個值來完成Future,然后get()將返回該值。

最簡單的使用方法是通過CompletableFuture類:

import java.util.concurrent.Future;
import java.util.concurrent.CompletableFuture;
...
public Future<Response> get(String endpoint) {
    return CompletableFuture.supplyAsync(() -> {
       return OffredUtil.makeGetRequest(endpoint);
    });
}

調用此get(endpoint)方法會將任務提交到將執行給定 lambda 表達式的內置線程池,然后它將返回將由任務完成的Future

如果 lambda 產生一個值,那么它將成為Future的值。 如果 lambda 拋出異常,則該異常將被捕獲,並且異常對象將存儲在Future

get(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());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM