所以我將ListenableFuture其用作某些操作的回傳型別。我希望用戶向未來添加回呼,然后處理成功和例外情況。現在,如果用戶無法處理例外,我希望能夠將該例外拋到主執行緒上。這是一些代碼示例:
public class SomeProcessor {
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
public ListenableFuture<String> doStringProcessing() {
return executor.submit(() -> doWork());
}
private String doWork() {
return "stuff";
}
}
然后在客戶端類中:
public class SomeConsumer {
public SomeConsumer (SomeProcessor processor) {
Futures.addCallback(processor.doStringProcessing(), new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
// do something with result
}
@Override
public void onFailure(Throwable t) {
if (t instanceof ExceptionICanHandle) {
// great, deal with it
} else {
// HERE I want to throw on the Main thread, not on the executor's thread
// Assume somehow I can get a hold of the main thread object
mainThread.getUncaughtExceptionHandler().uncaughtException(mainThread, t);
// This above code seems wrong???
throw new RuntimeException("Won't work as this is not on the mainthread");
}
}
}, MoreExecutors.directionExecutor());
}
}
uj5u.com熱心網友回復:
沒有直接的方法可以做到這一點。1個
因此,這個問題歸結為兩件簡單事情的組合:
- 我如何將提交的任務中的一些資料傳回管理池本身的代碼?歸結為:如何將資料從一個執行緒發送到另一個執行緒,以及......
- 我如何拋出例外 - 這是微不足道的 -
throw x;。
換句話說,你在你的任務中制造了例外,而不是throw它,而是將物件存盤在主執行緒可以看到它的地方,并通知主執行緒他們需要去獲取它并拋出它。您的主執行緒等待此通知,并在收到通知后獲取并拋出它。
提交的任務不能簡單地“請求”它的池或管理它的執行緒。然而,這很容易解決:只需將“主執行緒”本身,或者更可能是充當它們之間公共通信線路的某個第三方物件傳遞給任務本身,以便該任務知道去哪里。
這是一種基于嵌入到 Java 本身的原始同步原語的簡單方法:
public static void main(String[] args) {
// I am the main thread
// Fire up the executorservice here and submit tasks to it.
// then ordinarily you would let this thread end or sleep.
// instead...
ExecutorService service = ...;
AtomicReference<Throwable> err = new AtomicReference<>();
Runnable task = () -> doWork(err);
service.submit(task);
while (true) {
synchronized (err) {
Throwable t = err.get();
if (t != null) throw t;
err.wait();
}
}
}
public void doWork(AtomicReference<Throwable> envelope) {
try {
doActualWork();
catch (Throwable t) {
synchronized (envelope) {
envelope.set(t);
envelope.notifyAll();
}
}
}
有很多方法可以將訊息從一個執行緒發送到另一個執行緒,上面是一種相當挑剔的原始形式。如果您目前沒有任何可用的通訊頻道,它會很好。但是,如果您已經擁有例如訊息佇列服務或類似服務,您應該在這里使用它。
[1]Thread.stop(someThrowable)從字面上看是根據其自己的檔案執行此操作的。但是,它不起作用 - 它不僅已被棄用,而且已被完全砍掉;呼叫它會UnsupportedOperationException在現代 VM 上拋出一個錯誤(我認為此時至少有 10 年的版本價值),并且被標記為已棄用,并帶有相當不祥的警告This method is inherently unsafe。還有很多要啟動的,這不是正確的答案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/537360.html
標籤:爪哇多线程例外未来番石榴
下一篇:Microsoft.EntityFrameworkCore.DbUpdateException:'保存物體更改時出錯。有關詳細資訊,請參閱內部例外。
