美文网首页
Runnable、Callable、Future、FutureT

Runnable、Callable、Future、FutureT

作者: zc_sunny | 来源:发表于2021-02-02 10:04 被阅读0次

    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;
        }
    
    }
    

    相关文章

      网友评论

          本文标题:Runnable、Callable、Future、FutureT

          本文链接:https://www.haomeiwen.com/subject/fcystltx.html