выполнять : использовать его для огня и забыть о звонках
submit : используйте его, чтобы проверить результат вызова метода и предпринять соответствующие действияFuture
возражения, возвращенного вызовом
Из javadocs
submit(Callable<T> task)
Отправляет на выполнение задачу, возвращающую значение, и возвращает Future, представляющий ожидающие результаты задачи.
Future<?> submit(Runnable task)
Отправляет на выполнение задачу Runnable и возвращает Future, представляющую эту задачу.
void execute(Runnable command)
Выполняет заданную команду когда-нибудь в будущем. Команда может выполняться в новом потоке, в объединенном потоке или в вызывающем потоке по усмотрению реализации Executor.
При использовании необходимо соблюдать меры предосторожности submit()
. Он скрывает исключение в самой структуре, если вы не встраиваете код задачи в try{} catch{}
блок.
Пример кода: этот код проглатывает Arithmetic exception : / by zero
.
import java.util.concurrent.*;
import java.util.*;
public class ExecuteSubmitDemo{
public ExecuteSubmitDemo()
{
System.out.println("creating service");
ExecutorService service = Executors.newFixedThreadPool(10);
service.submit(new Runnable(){
public void run(){
int a=4, b = 0;
System.out.println("a and b="+a+":"+b);
System.out.println("a/b:"+(a/b));
System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName());
}
});
service.shutdown();
}
public static void main(String args[]){
ExecuteSubmitDemo demo = new ExecuteSubmitDemo();
}
}
выход:
java ExecuteSubmitDemo
creating service
a and b=4:0
Тот же код вызывает замену submit()
на execute
():
Заменить
service.submit(new Runnable(){
с участием
service.execute(new Runnable(){
выход:
java ExecuteSubmitDemo
creating service
a and b=4:0
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
at ExecuteSubmitDemo$1.run(ExecuteSubmitDemo.java:14)
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)
Как справиться с подобными сценариями при использовании submit ()?
- Встраивайте код задачи ( запускаемая или вызываемая реализация) с помощью кода блока try {} catch {}
- Осуществлять
CustomThreadPoolExecutor
Новое решение:
import java.util.concurrent.*;
import java.util.*;
public class ExecuteSubmitDemo{
public ExecuteSubmitDemo()
{
System.out.println("creating service");
ExtendedExecutor service = new ExtendedExecutor();
service.submit(new Runnable(){
public void run(){
int a=4, b = 0;
System.out.println("a and b="+a+":"+b);
System.out.println("a/b:"+(a/b));
System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName());
}
});
service.shutdown();
}
public static void main(String args[]){
ExecuteSubmitDemo demo = new ExecuteSubmitDemo();
}
}
class ExtendedExecutor extends ThreadPoolExecutor {
public ExtendedExecutor() {
super(1,1,60,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(100));
}
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
if (t != null)
System.out.println(t);
}
}
выход:
java ExecuteSubmitDemo
creating service
a and b=4:0
java.lang.ArithmeticException: / by zero
Runnable
завернуты вы в aTask
или нет, что вы не можете контролировать. Например, если выExecutor
на самом деле aScheduledExecutorService
, ваша задача будет внутренне обернута в a,Future
а неперехваченныеThrowable
s будут привязаны к этому объекту.