[英]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.