![](/img/trans.png)
[英]Future.get() gets interrupted always with an InterruptedException
[英]In what cases does Future.get() throw ExecutionException or InterruptedException
我的代碼片段:
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
Task t = new Task(response,inputToPass,pTypes,unit.getInstance(),methodName,unit.getUnitKey());
Future<SCCallOutResponse> fut = executor.submit(t);
response = fut.get(unit.getTimeOut(),TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
// if the task is still running, a TimeOutException will occur while fut.get()
cat.error("Unit " + unit.getUnitKey() + " Timed Out");
response.setVote(SCCallOutConsts.TIMEOUT);
} catch (InterruptedException e) {
cat.error(e);
} catch (ExecutionException e) {
cat.error(e);
} finally {
executor.shutdown();
}
我應該如何處理代碼中的InterruptedException
和ExecutionException
?
在什么情況下,會拋出這些異常?
ExecutionException
和InterruptedException
是兩個非常不同的東西。
ExecutionException
包裝了正在執行的線程拋出的任何異常,因此,例如,如果您的線程正在執行某種導致拋出IOException
的 IO,那么它將被包裝在ExecutionException
並重新拋出。
InterruptedException
並不是任何出錯的跡象。 它為您提供一種方法,讓您的線程知道何時該停止,以便它們可以完成當前的工作並優雅地退出。 假設我希望我的應用程序停止運行,但我不希望我的線程在某些事情中間放棄它們正在做的事情(如果我讓它們成為守護線程會發生什么)。 因此,當應用程序關閉時,我的代碼調用這些線程上的中斷方法,該方法在它們上設置中斷標志,下次這些線程等待或休眠時,它們檢查中斷標志並拋出InterruptedException
,我可以使用擺脫線程參與的任何無限循環處理/睡眠邏輯。(如果線程不等待或睡眠,它可以定期檢查中斷標志。)所以它是一個正在使用的異常實例改變邏輯流程。 您將其記錄下來的唯一原因是在示例程序中向您展示正在發生的事情,或者如果您正在調試中斷邏輯無法正常工作的問題。
InterruptedException
,如果將被拋出interrupt
被稱為等待線程計算完成之前。
如果所涉及的計算(在本例中為Task
)本身拋出異常,則將拋出ExecutionException
。
您想如何處理這將完全取決於您的應用程序。
編輯:這是被打斷的演示:
import java.util.concurrent.*;
public class Test
{
public static void main(String[] args) throws Exception
{
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(new SlowCallable());
executor.submit(new Interruptor(Thread.currentThread()));
try
{
System.out.println(future.get());
}
catch (InterruptedException e)
{
System.out.println("I was interrupted");
}
}
private static class Interruptor implements Callable<String>
{
private final Thread threadToInterrupt;
Interruptor(Thread threadToInterrupt)
{
this.threadToInterrupt = threadToInterrupt;
}
public String call() throws Exception
{
Thread.sleep(2000);
threadToInterrupt.interrupt();
return "interrupted other thread";
}
}
private static class SlowCallable implements Callable<String>
{
public String call() throws Exception
{
Thread.sleep(5000);
return "finished";
}
}
}
IBM Developer Works 文章 處理 InterruptedException有一些關於如何處理InterruptedException
建議。
返回三種異常類型的示例代碼。
import java.util.concurrent.*;
import java.util.*;
public class ExceptionDemo{
public static void main(String args[]){
int poolSize=1;
int maxPoolSize=1;
int queueSize=30;
long aliveTive=60;
ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
ThreadPoolExecutor executor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
TimeUnit.MILLISECONDS,queue);
List<Future> futures = new ArrayList<Future>();
for ( int i=0; i < 5; i++){
futures.add(executor.submit(new RunnableEx()));
}
for ( Iterator it = futures.iterator(); it.hasNext();){
try {
Future f = (Future)it.next();
f.get(4000,TimeUnit.MILLISECONDS);
}catch(TimeoutException terr){
System.out.println("Timeout exception");
terr.printStackTrace();
}
catch(InterruptedException ierr){
System.out.println("Interrupted exception:");
ierr.printStackTrace();
}catch(ExecutionException err){
System.out.println("Exeuction exception:");
err.printStackTrace();
Thread.currentThread().interrupt();
}
}
executor.shutdown();
}
}
class RunnableEx implements Runnable{
public void run() {
// code in here
System.out.println("Thread name:"+Thread.currentThread().getName());
try{
Random r = new Random();
if (r.nextInt(2) == 1){
Thread.sleep(2000);
}else{
Thread.sleep(4000);
}
System.out.println("eee:"+1/0);
}catch(InterruptedException irr){
irr.printStackTrace();
}
}
}
輸出:
Thread name:pool-1-thread-1
Timeout exception
Thread name:pool-1-thread-1
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
at ExceptionDemo.main(ExceptionDemo.java:20)
Thread name:pool-1-thread-1
Exeuction exception:
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:202)
at ExceptionDemo.main(ExceptionDemo.java:20)
Caused by: java.lang.ArithmeticException: / by zero
at RunnableEx.run(ExceptionDemo.java:49)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Interrupted exception:
java.lang.InterruptedException
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400)
at java.util.concurrent.FutureTask.get(FutureTask.java:199)
at ExceptionDemo.main(ExceptionDemo.java:20)
Timeout exception
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
Thread name:pool-1-thread-1
at ExceptionDemo.main(ExceptionDemo.java:20)
Thread name:pool-1-thread-1
Timeout exception
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
at ExceptionDemo.main(ExceptionDemo.java:20)
TimeoutException :阻塞操作超時時拋出的異常。
在上面的例子中,一些任務需要更多的時間(由於 4 秒睡眠)並且阻塞了Future
上的get()
操作
增加超時或優化 Runnable 任務。
ExecutionException : 嘗試檢索因拋出異常而中止的任務的結果時拋出的異常 => 計算拋出異常
在上面的例子中,這個Exception
是通過ArithmeticException: / by zero
模擬的
通常,如果如示例中引用的那樣微不足道,您應該抓住它來修復根本原因。
InterruptedException :當線程正在等待、睡眠或以其他方式被占用,並且線程在活動之前或期間被中斷時拋出。
在上面的例子中,這個Exception
是通過在ExecutionException
期間中斷當前 Thread 來模擬的。
一般來說,你應該抓住它而不是對它采取行動。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.