并发编程 --> Future , promise , callback

Java中的线程创建方式(回顾):

  1. 继承Thread类创建线程类,同时重写run()方法,将需要并发执行的业务逻辑代码编写在run()方法中。

  2. 实现Runnable接口创建线程目标类,实现类中重写run()方法,创建Thread类的对象(有参构造器,实现类对象作为参数)。

  3. 实现callable接口创建线程目标类.实现call()方法(有返回值),将实现类的对象作为参数传递到FutureTask构造器中.创建FutureTask的对象,将FutureTask的对象作为参数传入Thread的构造器中创建Thread对象。

  4. 使用线程池创建对象

    创建线程池的工具类: Executors -->创建并返回不同类型的线程池

    • Executors.newCachedThreadPool():创建一个可根据需要创建新线程的线程池(缓存线程池)

    • Executors.newFixedThreadPool():创建一个可重用固定线程数的线程池

    • Executors.newSingleThreadPool():创建一个只有一个线程的线程池

    • Executors.newScheduledThreadPool():创建一个线程池,可安排在给定延迟后运行命令或者定期执行

      自定义线程池:ThreadPoolExecutor构造函数

异步操作的有两个经典接口:Future 和 Promise,其中的 Future 表示一个可能还没有实际完成的异步任务的结果,针对这个结果可以添加 Callback 以便在任务执行成功或失败后做出对应的操作,而 Promise 交由任务执行者,任务执行者通过 Promise 可以标记任务完成或者失败。 可以说这一套模型是很多异步非阻塞架构的基础。

Future

Future模式核心思想:异步执行,同步返回

Future模式可以理解为将任务提交给线程执行,其执行结果为Future(未来的结果),期间可以去做其他事情,等需要结果时,再从Future那里get()方法阻塞等待或isDone方法轮询等待结果(获取结果,执行完直接返回结果,没有执行完则阻塞等待返回)。

JDK的Future

public interface Future<V> {
    // 取消异步操作
    boolean cancel(boolean mayInterruptIfRunning);
    // 异步操作是否取消
    boolean isCancelled();
    // 异步操作是否完成,正常终止、异常、取消都是完成
    boolean isDone();
​
    // 阻塞直到取得异步操作结果
    V get() throws InterruptedException, ExecutionException;
    // 同上,但最长阻塞时间为timeout
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

查看JDK中的Future接口,我们发现Future是一个只读的结构,一旦任务被提交除了取消任务外就不可能改变任务。

Future模式在JDK一般如下使用,创建对应的异步任务.然后需要结果时主动调用get方法

public static ExecutorService executorService = Executors.newFixedThreadPool(3);
    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        long start = System.currentTimeMillis();
        //把耗时任务放入异步线程
        FutureTask<String> task = new FutureTask<>(()->{
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(1000L);
            return "test";
        });
        //提交任务
        executorService.submit(task);
        //模拟耗时操作
        Thread.sleep(1000L);
        //获取结果
        String result = task.get(1000L,TimeUnit.MILLISECONDS);
        System.out.println(result);
        System.out.println(Thread.currentThread().getName() + " : " + (System.currentTimeMillis()-start));
        executorService.shutdown();
    }

JDK的Future的原理

从代码角度看,一个FutureTask会经历以下几个过程。

  1. 接受任务

    FutureTask首先会接受一个Callable任务的任务,在FutureTask的构造方法中,我们看到state(自身状态)设置为NEW

    public FutureTask(Callable<V> callable) {
            if (callable == null)
                throw new NullPointerException();
            this.callable = callable;
            this.state = NEW;       // ensure visibility of callable
        }
    //如果提交Runnable任务,最后也会变成callable类型
    public FutureTask(Runnable runnable, V result) {
            this.callable = Executors.callable(runnable, result);
            this.state = NEW;       // ensure visibility of callable
        }

    state几种状态(仅在set,setException,cancel方法中转换为终端状态)

    终端状态有四种: NORMAL结果正常、EXCEPTIONAL结果异常、CANCELLED任务取消、INTERRUPTED任务中断

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值