• 第二部分:并发工具类23->多线程实现最优烧水泡茶


    1.如何使用线程池

    ThreadPoolExecutor是否提供了获取任务执行结果的功能呢

    2.如何获取任务执行结果

    3个sumit方法+1个futureTask工具类

    Future<?> submit(Runnable task);
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task,T result);
    

    1.sumit方法的参数是Runnable接口,run方法是没有返回值,所以submit方法的返回future只可以用来判断是否已经结束,类似thread.join()
    2.submit方法的参数是Callable接口,它只有一个call方法,并且这个方法是有返回值,方法返回的future对象可以通过调用其get方法获取任务执行结果
    3.submit方法的参数是Runnable接口+泛型result,f.get()返回值就是传给submit()方法的参数result。Runnable接口的实现类要有有参Result的构造函数,run函数中修改result对象

    future接口,有5个方法,

    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    get();
    get(long timeout,TimeUnit unit);
    

    3.FutureTask工具类

    FutureTask是工具类,Future是接口
    FutureTask是对Runnable或者Callable接口的实现类进行的再次封装,可以直接使用获取返回结果
    两个构造函数

    FutureTask(Callable<V> callable);
    FutureTask(Runnable runnable,V result);
    

    范例

    FutureTask<Integer> futureTask = new FutureTask<>( () -> 1 + 2);
    
    ExecutorService es = Executors.newCachedThreadPool();
    
    es.submit(futureTask);
    
    Integer result = futureTask.get();
    

    4.两个线程协作

    线程T1等待T2执行完,再执行T1 的其余动作

    
    // 创建任务T2的FutureTask
    FutureTask<String> ft2
      = new FutureTask<>(new T2Task());
    // 创建任务T1的FutureTask
    FutureTask<String> ft1
      = new FutureTask<>(new T1Task(ft2));
    // 线程T1执行任务ft1
    Thread T1 = new Thread(ft1);
    T1.start();
    // 线程T2执行任务ft2
    Thread T2 = new Thread(ft2);
    T2.start();
    // 等待线程T1执行结果
    System.out.println(ft1.get());
    
    // T1Task需要执行的任务:
    // 洗水壶、烧开水、泡茶
    class T1Task implements Callable<String>{
      FutureTask<String> ft2;
      // T1任务需要T2任务的FutureTask
      T1Task(FutureTask<String> ft2){
        this.ft2 = ft2;
      }
      @Override
      String call() throws Exception {
        System.out.println("T1:洗水壶...");
        TimeUnit.SECONDS.sleep(1);
        
        System.out.println("T1:烧开水...");
        TimeUnit.SECONDS.sleep(15);
        // 获取T2线程的茶叶  
        String tf = ft2.get();
        System.out.println("T1:拿到茶叶:"+tf);
    
        System.out.println("T1:泡茶...");
        return "上茶:" + tf;
      }
    }
    // T2Task需要执行的任务:
    // 洗茶壶、洗茶杯、拿茶叶
    class T2Task implements Callable<String> {
      @Override
      String call() throws Exception {
        System.out.println("T2:洗茶壶...");
        TimeUnit.SECONDS.sleep(1);
    
        System.out.println("T2:洗茶杯...");
        TimeUnit.SECONDS.sleep(2);
    
        System.out.println("T2:拿茶叶...");
        TimeUnit.SECONDS.sleep(1);
        return "龙井";
      }
    }
    // 一次执行结果:
    T1:洗水壶...
    T2:洗茶壶...
    T1:烧开水...
    T2:洗茶杯...
    T2:拿茶叶...
    T1:拿到茶叶:龙井
    T1:泡茶...
    上茶:龙井
    

    5.总结

    future类比现实世界的提货单,拿到提货单后,没必要在店里一直待着,可以去干别的事

    多线程可以将串行任务并行化,提高性能。任务之间有依赖关系,当前任务依赖前一个任务的执行结果,可以用future来解决。

    原创:做时间的朋友
  • 相关阅读:
    敏捷之Scrum框架
    Google浏览器80版本以上无法打开系统页面问题
    ThreadLocal 了解
    简化两个list之间赋值操作
    linux下用命令调用dubbo服务
    13条代码审查建议
    初识MongoDB(1)
    linux日常常用命令整理
    java发起http请求
    工作思维方法
  • 原文地址:https://www.cnblogs.com/PythonOrg/p/14986972.html
Copyright © 2020-2023  润新知