Runnable、Callable、Future、FutureTask

Runnable、Callable、Future、FutureTask

一:并发编程的核心

并发编程的核心问题:分工、同步和互斥。
要编写高质量的并发程序,只需要处理好分工、同步和互斥的问题即可,同步和互斥对应的就是管程模型

二:Runnable、Callable、Future、FutureTask

1:Runnable、Callable、Future、FutureTask的UML类图

Callable与Runnable、Future、FutureTask无继承关系。
FutureTask带了Future和Runnable的功能。


Runnable....png

2:Runnable和Callable

// JDK1.0 不接受参数、无返回值,单线程、线程池均可使用。
public interface Runnable {

  public abstract void run();
  
}

// JDK 1.5 不接受参数、有返回值,仅供线程池使用。
public interface Callable<V> {

  V call() throws Exception;

}

3:Future API

// 取消任务
boolean cancel( boolean mayInterruptIfRunning);

// 判断任务是否已取消
boolean isCancelled();

// 判断任务是否已结束
boolean isDone();

// 获得任务执行结果 ---> 阻塞方法
get();

// 获得任务执行结果,支持超时 ---> 阻塞方法
get(long timeout, TimeUnit unit);

4:为什么要引入FutureTask?为什么要让FutureTask实现Runnable?

在单线程和多线程执行Task的时候,都有获取执行结果的需求,但是当使用Runnable的时候,Runnable的API是拿不到返回值的,因此可以用FutureTask类包装Runnable来拿返回值。
所以:Runnable、Callable、Future、FutureTask存在的目的是为了使用更加灵活。

获取执行结果:

  • 单线程:FutureTask包装Callable和Runnable,通过FutureTask获取返回值。
  • 多线程:单独使用Callable能获取返回值,FutureTask包装Callable和Runnable能获取返回值。

5:使用示例

/**
 * <p>
 * Runnable、Callable、Future、FutureTask
 * </p>
 *
 * @author: Sunny
 * @date: 2021/2/1
 * @version: v1.0.0
 */
public class TaskTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1:单线程 + Callable + FutureTask拿到返回结果
        FutureTask<Integer> task = new FutureTask<Integer>(() -> {
            return 1 + 1;
        });
        Thread t1 = new Thread(task);
        t1.start();
        System.out.println(task.get());

        // 2:单线程 + Runnable + T result + FutureTask拿到返回结果
        Account account = new Account();
        FutureTask<Account> task1 = new FutureTask<Account>(() -> {
            account.setName("zhangsan");
            account.setAge(3);
        }, account);
        Thread t2 = new Thread(task1);
        t2.start();
        System.out.println(task1.get().getName() + " : " + task1.get().getAge());
        System.out.println(account.getName() + " : " + account.getAge());

        // 3:线程池 + Callable + Future拿到返回结果
        ExecutorService service = Executors.newSingleThreadExecutor();
        Future<Integer> future = service.submit(() -> 1 + 1);
        System.out.println(future.get());

        // 4:线程池 + Runnable + Future拿不到返回结果
        Future<?> future1 = service.submit(() -> System.out.println(1));
        // Runnable 不接受返回值,因此其值为null
        System.out.println(future1.get());

        // 5:线程池 + Runnable +  T result + Future拿到返回结果
        Account account1 = new Account();
        Future<Account> future2 = service.submit(() -> {
            account1.setName("xiaoming");
            account1.setAge(4);
        }, account1);
        System.out.println(future2.get().getName() + " : " + future2.get().getAge());
        System.out.println(account1.getName() + " : " + account1.getAge());
        service.shutdown();
    }

    @Data
    public static class Account {
        private String name;
        private Integer age;
    }

}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容