JUC之Future/Task框架

 

引入了一个”执行服务”的概念,它将”任务的提交”和”任务的执行”相分离,”执行服务”封装了任务执行的细节,对于任务提交者而言,它可以关注于任务本身,如提交任务、获取结果、取消任务,而不需要关注任务执行的细节,如线程创建、任务调度、线程关闭等。

基本接口
任务执行服务涉及的基本接口:

Runnable和Callable:表示要执行的异步任务
Executor和ExecutorService:表示执行服务
Future:表示异步任务的结果
Executor和ExecutorService
Executor表示最简单的执行服务,其定义为:

public interface Executor {
    void execute(Runnable command);
}
就是可以执行一个Runnable,没有返回结果。接口没有限定任务如何执行,可能是创建一个新线程,可能是复用线程池中的某个线程,也可能是在调用者线程中执行。

ExecutorService扩展了Executor,定义了更多服务,基本方法有:

public interface ExecutorService extends Executor {
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    Future<?> submit(Runnable task);
    //… 其他方法
}
这三个submit都表示提交一个任务,返回值类型都是Future,返回后,只是表示任务已提交,不代表已执行,通过Future可以查询异步任务的状态、获取最终结果、取消任务等。我们知道,对于Callable,任务最终有个返回值,而对于Runnable是没有返回值的,第二个提交Runnable的方法可以同时提供一个结果,在异步任务结束时返回,而对于第三个方法,异步任务的最终返回值为null。

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。

cancel用于取消异步任务,如果任务已完成、或已经取消、或由于某种原因不能取消,cancel返回false,否则返回true。如果任务还未开始,则不再运行。
isDone和isCancelled用于查询任务状态。

get方法,任务有三个结果:
1>正常完成,get方法会返回其执行结果,如果任务是Runnable且没有提供结果,返回null
2>任务执行抛出了异常,get方法会将异常包装为ExecutionException重新抛出,通过异常的getCause方法可以获取原异常
3>任务被取消了,get方法会抛出异常CancellationException

如果调用get方法的线程被中断了,get方法会抛出InterruptedException。

总结
Future是一个重要的概念,是实现”任务的提交”与”任务的执行”相分离的关键,是其中的”纽带”,任务提交者和任务执行服务通过它隔离各自的关注点,同时进行协作。

示例
public class BasicDemo {
    static class Task implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            int sleepSeconds = new Random().nextInt(1000);
            Thread.sleep(sleepSeconds);
            return sleepSeconds;
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Integer> future = executor.submit(new Task());
        // 模拟执行其他任务
        Thread.sleep(100);
        try {
            System.out.println(future.get());
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        executor.shutdown();
    }
}
死锁示例
public class DeadLockDemo {
    private static Object lockA = new Object();
    private static Object lockB = new Object();
    private static void startThreadA() {
        Thread aThread = new Thread() {
            @Override
            public void run() {
                synchronized (lockA) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    synchronized (lockB) {
                    }
                }
            }
        };
        aThread.start();
    }
    private static void startThreadB() {
        Thread bThread = new Thread() {
            @Override
            public void run() {
                synchronized (lockB) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    synchronized (lockA) {
                    }
                }
            }
        };
        bThread.start();
    }
    public static void main(String[] args) {
        startThreadA();
        startThreadB();
    }
}

    原文作者:JUC
    原文地址: https://blog.csdn.net/yang_154116/article/details/81106216
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞