异步任务是如何运转的
任务执行服务涉及的基本接口:
- Runnable和Callable:表示要执行的异步任务。Runnable没有返回结果,而Callable有,Runnable不会抛出异常,而Callable会。
- Executor和ExecutorService:表示执行服务。
- Future:表示异步任务的结果。
Runnable、Callable
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
Executor
public interface Executor {
void execute(Runnable command);
}
public interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
<T> List<Future<T>> invokeAll(
Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit
) throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
<T> T invokeAny(
Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit
) throws InterruptedException, ExecutionException, TimeoutException;
}
三个submit都表示提交一个任务,返回值类型都是Future,返回后,只是表示任务已提交,不代表已执行,通过Future可以查询异步任务的状态、获取最终结果、取消任务等。
两个关闭方法shutdown和shutdownNow
区别是:
- shutdown表示不再接受新任务,但已提交的任务会继续执行,即使任务还未开始执行;
- shutdownNow不仅不接受新任务,而且会终止已提交但尚未执行的任务,对于正在执行的任务,一般会调用线程的interrupt方法尝试中断,不过,线程可能不响应中断,shutdownNow会返回已提交但尚未执行的任务列表。
shutdown和shutdownNow不会阻塞等待,它们返回后不代表所有任务都已结束,不过isShutdown方法会返回true。调用者可以通过awaitTermination等待所有任务结束,它可以限定等待的时间,如果超时前所有任务都结束了,即isTerminated方法返回true,则返回true,否则返回false。
两组批量提交任务的方法invokeAll和invokeAny
- invokeAll等待所有任务完成,返回的Future列表中,每个Future的isDone方法都返回true,不过isDone为true不代表任务就执行成功了,可能是被取消了。invokeAll可以指定等待时间,如果超时后有的任务没完成,就会被取消。
- invokeAny,只要有一个任务在限时内成功返回了,它就会返回该任务的结果,其他任务会被取消;如果没有任务能在限时内成功返回,抛出TimeoutException;如果限时内所有任务都结束了,但都发生了异常,抛出ExecutionException。
Future
Future是一个重要的概念,是实现“任务的提交”与“任务的执行”相分离的关键,是其中的“纽带”,任务提交者和任务执行服务通过它隔离各自的关注点,同时进行协作。
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException;
}
get用于返回异步任务最终的结果,如果任务还未执行完成,会阻塞等待,另一个get方法可以限定阻塞等待的时间,如果超时任务还未结束,会抛出TimeoutException。
任务最终大概有三种结果:
- 正常完成,get方法会返回其执行结果,如果任务是Runnable且没有提供结果,返回null。
- 任务执行抛出了异常,get方法会将异常包装为ExecutionException重新抛出,通过异常的getCause方法可以获取原异常。
- 任务被取消了,get方法会抛出异常CancellationException。
如果调用get方法的线程被中断了,get方法会抛出InterruptedException。
cancel用于取消异步任务,如果任务已完成、或已经取消、或由于某种原因不能取消, cancel返回false,否则返回true。
如果任务还未开始,则不再运行。
如果任务已经在运行,则不一定能取消,参数mayInterruptIfRunning表示,如果任务正在执行,是否调用interrupt方法中断线程,如果为false就不会,如果为true,就会尝试中断线程,注意,中断不一定能取消线程。
isDone和isCancelled用于查询任务状态。
isCancelled表示任务是否被取消,只要cancel方法返回了true,随后的isCancelled方法都会返回true,即使执行任务的线程还未真正结束。
isDone表示任务是否结束,不管什么原因都算,可能是任务正常结束,可能是任务抛出了异常,也可能是任务被取消。
#java原理##并发编程#知其然知其所以然,只有掌握了底层原理,借助第一性原理,才可以在日常开发和项目中运用自如,潇洒走江湖。 专为27届毕业生准备,托起您的就业梦。 该专辑会不定时更新,建议27届同学订阅,入职后扎实的基本功可以帮您争取更好的机会和项目。