并发编程-21J.U.C组件拓展之Future和FutureTask

简介: 并发编程-21J.U.C组件拓展之Future和FutureTask

2019080611330380.jpg

概述


Future接口和实现Future接口的FutureTask类,代表异步计算的结果。


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


FutureTask的三种运行状态


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



20190303172143257.png

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

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

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


FutureTask的三种运行状态下的get/cancel操作及结果



2019030317264666.png



当FutureTask处于未启动或已启动状态时,执行FutureTask.get()方法将导致调用线程阻塞


当FutureTask处于已完成状态时,执行FutureTask.get()方法将导致调用线程立即返回结果或抛出异常


当FutureTask处于未启动状态时,执行FutureTask.cancel()方法将导致此任务永远不会被执行


当FutureTask处于已启动状态时,执行FutureTask.cancel(true)方法将以中断执行此任务线程的方式来试图停止任务


当FutureTask处于已启动状态时,执行FutureTask.cancel(false)方法将不会对正在执行此任务的线程产生影响(让正在执行的任务运行完成)


当FutureTask处于已完成状态时,执行FutureTask.cancel(…)方法将返回false。


FutureTask的实现


FutureTask的实现基于AbstractQueuedSynchronizer(AQS)。


AQS是一个同步框架,它提供通用机制来原子性管理同步状态、阻塞和唤醒线程,以及维护被阻塞线程的队列。


基于AQS实现的同步器包括:ReentrantLock、Semaphore、ReentrantReadWriteLock、CountDownLatch和FutureTask


并发编程-15并发容器(J.U.C)核心 AbstractQueuedSynchronizer 抽象队列同步器AQS介绍


每一个基于AQS实现的同步器都会包含两种类型的操作


至少一个acquire操作。这个操作阻塞调用线程,除非/直到AQS的状态允许这个线程继续执行。FutureTask的acquire操作为get()/get(long timeout,TimeUnit unit)方法调用


至少一个release操作。这个操作改变AQS的状态,改变后的状态可允许一个或多个阻塞线程被解除阻塞。FutureTask的release操作包括run()方法和cancel(…)方法


基于“复合优先于继承”的原则,FutureTask声明了一个内部私有的继承于AQS的子类Sync,对FutureTask所有公有方法的调用都会委托给这个内部子类


AQS被作为“模板方法模式”的基础类提供给FutureTask的内部子类Sync,这个内部子类只需要实现状态检查和状态更新的方法即可,这些方法将控制FutureTask的获取和释放操作。具体来说,Sync实现了AQS的tryAcquireShared(int)方法和tryReleaseShared(int)方法,Sync通过这两个方法来检查和更新同步状态。


20190303173527202.png


FutureTask的使用


  • 可以把FutureTask交给Executor执行
  • 也可以通过ExecutorService.submit(…)方法返回一个FutureTask,然后执行FutureTask.get()方法或FutureTask.cancel(…)方法
  • 除此以外,还可以单独使用FutureTask

当一个线程需要等待另一个线程把某个任务执行完后它才能继续执行,此时可以使用FutureTask.


示例

Future

package com.artisan.example.aqs;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Slf4j
public class FutureExample {
    static class MyCallable implements Callable<String> {
        @Override
        public String call() throws Exception {
          // 耗时任务
            log.info("do something in callable start");
            Thread.sleep(5000);
            log.info("do something in callable  end");
            return "DONE";
        }
    }
    public static void main(String[] args) throws Exception {
      // 创建一个newCachedThreadPool线程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        // submit任务
        Future<String> future = executorService.submit(new MyCallable());
        // 主线程模拟一些业务操作,假设耗时一秒
        log.info("do something in main begin");
        Thread.sleep(1000);
        log.info("do something in main finish");
        // 获取刚才提交的线程MyCallable的返回结果
        log.info("获取MyCallable的返回结果,如果未返回,主线程将阻塞,处于等待状态");
        String result = future.get();
        log.info("result:{}", result);
    // 关闭线程池
        executorService.shutdown();
    }
}

观察执行结果:


2019030316413359.png

FutureTask

package com.artisan.example.aqs;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FutureTaskExample {
    public static void main(String[] args) throws Exception {
        FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
            @Override
            public String call() throws Exception {
              // 耗时任务
                log.info("do something in callable");
                Thread.sleep(5000);
                return "DONE";
            }
        });
        //创建一个newCachedThreadPool线程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        // execute futureTask任务
        executorService.execute(futureTask);
        // 主线程模拟一些业务操作,假设耗时一秒
        log.info("do something in main begin");
        Thread.sleep(1000);
        log.info("do something in main finish");
        // 获取刚才提交的线程MyCallable的返回结果
        log.info("获取futureTask的返回结果,如果未返回,主线程将阻塞,处于等待状态");
        String result = futureTask.get();
        log.info("result:{}", result);
    // 关闭线程池
        executorService.shutdown();
    }
}



20190303170711532.png


代码


https://github.com/yangshangwei/ConcurrencyMaster

相关文章
|
7月前
|
存储 Java
高并发编程之多线程锁和Callable&Future 接口
高并发编程之多线程锁和Callable&Future 接口
85 1
|
5月前
|
缓存 Java 调度
Java并发编程:深入解析线程池与Future任务
【7月更文挑战第9天】线程池和Future任务是Java并发编程中非常重要的概念。线程池通过重用线程减少了线程创建和销毁的开销,提高了资源利用率。而Future接口则提供了检查异步任务状态和获取任务结果的能力,使得异步编程更加灵活和强大。掌握这些概念,将有助于我们编写出更高效、更可靠的并发程序。
|
1月前
|
消息中间件 缓存 安全
Future与FutureTask源码解析,接口阻塞问题及解决方案
【11月更文挑战第5天】在Java开发中,多线程编程是提高系统并发性能和资源利用率的重要手段。然而,多线程编程也带来了诸如线程安全、死锁、接口阻塞等一系列复杂问题。本文将深度剖析多线程优化技巧、Future与FutureTask的源码、接口阻塞问题及解决方案,并通过具体业务场景和Java代码示例进行实战演示。
47 3
|
2月前
|
Java 数据库 数据安全/隐私保护
关于并发编程,你必须需要掌握的Future机制!
关于并发编程,你必须需要掌握的Future机制!
|
3月前
|
Java
JAVA并发编程系列(13)Future、FutureTask异步小王子
本文详细解析了Future及其相关类FutureTask的工作原理与应用场景。首先介绍了Future的基本概念和接口方法,强调其异步计算特性。接着通过FutureTask实现了一个模拟外卖订单处理的示例,展示了如何并发查询外卖信息并汇总结果。最后深入分析了FutureTask的源码,包括其内部状态转换机制及关键方法的实现原理。通过本文,读者可以全面理解Future在并发编程中的作用及其实现细节。
|
7月前
并发编程之Callable方法的详细解析(带小案例)
并发编程之Callable方法的详细解析(带小案例)
104 0
|
7月前
|
Java
Java并发编程:理解并使用Future和Callable接口
【2月更文挑战第25天】 在Java中,多线程编程是一个重要的概念,它允许我们同时执行多个任务。然而,有时候我们需要等待一个或多个线程完成,然后才能继续执行其他任务。这就需要使用到Future和Callable接口。本文将深入探讨这两个接口的用法,以及它们如何帮助我们更好地管理多线程。
|
7月前
|
前端开发 JavaScript Java
每日一博 - Java 异步编程的 Promise 模式 CompletableFuture的前世今生 (上)
每日一博 - Java 异步编程的 Promise 模式 CompletableFuture的前世今生 (上)
231 0
每日一博 - Java 异步编程的 Promise 模式 CompletableFuture的前世今生 (上)
|
存储 Java
并发编程系列教程(09) - Callable与Future模式
并发编程系列教程(09) - Callable与Future模式
57 0
|
Java
异步编程 - 04 基于JDK中的Future实现异步编程(上)_Future & FutureTask 源码解析
异步编程 - 04 基于JDK中的Future实现异步编程(上)_Future & FutureTask 源码解析
81 0