Java-进阶篇-FutureTask初使用

  1. 1. FutureTask简介
  2. 2. FutureTask状态迁移
    1. 2.1 get和cancel使用介绍
  3. 3. FutureTask使用
    1. 3.1 计算1~10阶乘的和
    2. 3.2 futureTask实现
    3. 3.2 串行实现
  4. 4.参考链接

1. FutureTask简介

FutureTask除了实现Future接口外,还实现了Runnable接口。因此,FutureTask可以交给Executor执行,也可以由调用线程直接执行(FutureTask.run())。

根据FutureTask.run()方法被执行的时机,FutureTask可以处于下面3种状态。

  1. 未启动。FutureTask.run()方法还没有被执行之前,FutureTask处于未启动状态。当创建一个FutureTask,且没有执行FutureTask.run()方法之前,这个FutureTask处于未启动状态。

  2. 已启动。FutureTask.run()方法被执行的过程中,FutureTask处于已启动状态。

  3. 已完成。FutureTask.run()方法执行完后正常结束,或被取消(FutureTask.cancel(…)),或执行FutureTask.run()方法时抛出异常而异常结束,FutureTask处于已完成状态。

2. FutureTask状态迁移

2.1 get和cancel使用介绍

  • 当FutureTask处于未启动或已启动状态时,执行FutureTask.get()方法将导致调用线程阻塞;
  • 当FutureTask处于已完成状态时,执行FutureTask.get()方法将导致调用线程立即返回结果或抛出异常。
  • 当FutureTask处于未启动状态时,执行FutureTask.cancel()方法将导致此任务永远不会被执行;
  • 当FutureTask处于已启动状态时,执行FutureTask.cancel(true)方法将以中断执行此任务线程的方式来试图停止任务;
  • 当FutureTask处于已启动状态时,执行FutureTask. cancel(false)方法将不会对正在执行此任务的线程产生影响(让正在执行的任务运行完成);
  • 当FutureTask处于已完成状态时,执行FutureTask.cancel(…)方法将返回false。

以上内容摘自《Java并发的艺术》第十章第四节 FutureTask详情 片段。

3. FutureTask使用

3.1 计算1~10阶乘的和

10! + 9! + ...+1! = ?

阶乘的概念:

3.2 futureTask实现

package com.hui.javalearn.thread.futureTask;

import java.util.ArrayList;
import java.util.concurrent.*;

/**
 * description :
 *
 * @author : Mr.Liuqh
 * @date : 2019-12-30 11:55
 */
public class FutureTaskTest {
    /**
     * 并行计算
     */
    public void testTask() {
        long beginTime = System.currentTimeMillis();
        // 实例化本类,用于后续使用内部类实例化
        FutureTaskTest futureTaskTest = new FutureTaskTest();

        // 创建任务列表
        ArrayList<FutureTask<Integer>> futureTaskList = new ArrayList<>();
        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 1; i <= 10; i++) {
            // 传入Callable对象创建FutureTask对象
            FutureTask<Integer> futureTask = new FutureTask<>(futureTaskTest.new ComputerTask(i));
            // 添加到任务列表
            futureTaskList.add(futureTask);
            // 提交给线程池执行任务,也可以通过exec.invokeAll(taskList)一次性提交所有任务
            executorService.submit(futureTask);
        }

        // 任务已经提交完
        System.out.println("任务已经提交完,主线程继续执行....");
        // 获取任务结果
        ArrayList<Integer> taskResultList = new ArrayList<>();
        for (FutureTask<Integer> futureTaskItem : futureTaskList) {
            try {
                // 获取任务执行结果,会造成主线程阻塞
                Integer total = futureTaskItem.get();
                taskResultList.add(total);
            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 求和
        Integer integer = taskResultList.stream().reduce(Integer::sum).get();
        long useTime = (System.currentTimeMillis() - beginTime) / 1000L;
        System.out.println("10! + 9! + ...+1! =  " + integer );
        System.out.println(" 一共耗时:" + useTime + "秒");

        // 关闭线程池
        executorService.shutdown();
        System.out.println("任务执行完毕。");

    }

    /**
     * desc : 定义内部类
     **/
    private class ComputerTask implements Callable<Integer> {
        private Integer num;
        private Integer total;

        ComputerTask(Integer i) {
            this.num = i;
        }

        @Override
        public Integer call() throws Exception {
            total = 1;
            String s ="";
            for (int i = 1; i <= this.num; i++) {
                total *= i;
                s = s.concat(String.valueOf(i)).concat(" * ");
            }
            // 字符串截取
            String substring = s.substring(0,s.length()-2);
            // 休眠1秒钟,逾期主线程会继续执行,在主线程调用futureTask.get(),会阻塞,等待结果返回
            Thread.sleep(1000);
            System.out.println(substring + " = " + total);
            return total;
        }
    }
}

...
// 运行
new FutureTaskTest().testTask();

/*
输出:

任务已经提交完,主线程继续执行....
1 * 2  = 2
1 * 2 * 3 * 4 * 5 * 6 * 7  = 5040
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10  = 3628800
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9  = 362880
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8  = 40320
1 * 2 * 3  = 6
1 * 2 * 3 * 4 * 5 * 6  = 720
1 * 2 * 3 * 4  = 24
1  = 1
1 * 2 * 3 * 4 * 5  = 120
10! + 9! + ...+1! =  4037913
 一共耗时:1秒
任务执行完毕。

3.2 串行实现

package com.hui.javalearn.thread.futureTask;

import java.util.ArrayList;
import java.util.concurrent.*;

/**
 * description :
 *
 * @author : Mr.Liuqh
 * @date : 2019-12-30 11:55
 */
public class FutureTaskTest {
    /**
     * desc : 定义内部类
     **/
    private class ComputerTask implements Callable<Integer> {
        private Integer num;
        private Integer total;

        ComputerTask(Integer i) {
            this.num = i;
        }

        @Override
        public Integer call() throws Exception {
            total = 1;
            String s ="";
            for (int i = 1; i <= this.num; i++) {
                total *= i;
                s = s.concat(String.valueOf(i)).concat(" * ");
            }
            // 字符串截取
            String substring = s.substring(0,s.length()-2);
            // 休眠1秒钟,逾期主线程会继续执行,在主线程调用futureTask.get(),会阻塞,等待结果返回
            Thread.sleep(1000);
            System.out.println(substring + " = " + total);
            return total;
        }
    }
    /**
    *  串行计算
    */
    public void testSerialTask() throws Exception {
        long beginTime = System.currentTimeMillis();
        FutureTaskTest futureTaskTest = new FutureTaskTest();
        ArrayList<Integer> taskResultList = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            Integer call = futureTaskTest.new ComputerTask(i).call();
            taskResultList.add(call);
        }
        // 求和
        Integer integer = taskResultList.stream().reduce(Integer::sum).get();
        long useTime = (System.currentTimeMillis() - beginTime) / 1000L;
        System.out.println("10! + 9! + ...+1! =  " + integer );
        System.out.println("一共耗时:" + useTime + "秒");

    }
}

...

// 运行


/*
输出:

1  = 1
1 * 2  = 2
1 * 2 * 3  = 6
1 * 2 * 3 * 4  = 24
1 * 2 * 3 * 4 * 5  = 120
1 * 2 * 3 * 4 * 5 * 6  = 720
1 * 2 * 3 * 4 * 5 * 6 * 7  = 5040
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8  = 40320
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9  = 362880
1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10  = 3628800
10! + 9! + ...+1! =  4037913
一共耗时:10秒

查看源码

4.参考链接


转载请注明来源,欢迎指出任何有错误或不够清晰的表达。

文章标题:Java-进阶篇-FutureTask初使用

文章字数:1.3k

本文作者:猿码记

发布时间:2019-12-20 12:31

原始链接:liuqh.icu/2019/12/20/java-17-FutureTask初使用/

版权声明: 转载请保留原文链接及作者。

目录
×

看您心情~~