模块  java.base
软件包  java.util.concurrent

Class ForkJoinTask<V>

  • 实现的所有接口
    SerializableFuture<V>
    已知直接子类:
    CountedCompleterRecursiveActionRecursiveTask

    public abstract class ForkJoinTask<V>extends Objectimplements Future<V>, Serializable
    ForkJoinPool内运行的任务的抽象基类。 ForkJoinTask是一个类似于线程的实体,其重量比普通线程轻得多。 大量的任务和子任务可能由ForkJoinPool中的少量实际线程托管,代价是一些使用限制。

    A“主” ForkJoinTask开始执行时,明确提出到ForkJoinPool ,或者,如果不是已经从事ForkJoin计算,在开始ForkJoinPool.commonPool()通过fork()invoke() ,或相关方法。 一旦启动,它通常会依次启动其他子任务。 如该类的名称所示,许多使用ForkJoinTask程序ForkJoinTask采用方法fork()join() ,或诸如invokeAll衍生物。 但是,这个类还提供了许多其他可以在高级用法中发挥作用的方法,以及允许支持新形式的fork / join处理的扩展机制。

    ForkJoinTask是轻质形式Future ForkJoinTask的效率源于一系列限制(仅部分静态可执行),反映了它们作为计算任务计算纯函数或在纯粹孤立对象上运行的主要用途。 主要协调机制是fork() ,它安排异步执行, join() ,在计算任务结果之前不会继续。 理想情况下,计算应避免使用synchronized方法或块,并且应该最小化其他阻塞同步,除了加入其他任务或使用同步器(如Phasers),这些同步器通告为与fork / join调度协作。 子分类任务也不应该执行阻塞I / O,理想情况下应该访问完全独立于其他正在运行的任务访问的变量。 不允许抛出诸如IOExceptions类的已检查异常,因此松散地强制执行这些准则。 但是,计算可能仍会遇到未经检查的异常,这些异常会被尝试加入它们的调用者重新抛出。 这些例外可能还包括源于内部资源耗尽的RejectedExecutionException ,例如无法分配内部任务队列。 Rethrown异常的行为方式与常规异常相同,但是,如果可能,包含启动计算的线程以及实际遇到异常的线程的堆栈跟踪(如使用ex.printStackTrace() ); 最低限度只有后者。

    可以定义和使用可能阻塞的ForkJoinTasks,但这样做需要进一步考虑:(1)如果任何其他任务应该依赖于阻止外部同步或I / O的任务,则完成很少。 从未加入的事件样式异步任务(例如,那些子类化CountedCompleter )通常属于此类别。 (2)为了尽量减少资源影响,任务应该很小; 理想情况下只执行(可能)阻止操作。 (3)除非使用ForkJoinPool.ManagedBlocker API,或者已知可能阻塞的任务数小于池的ForkJoinPool.getParallelism()级别, 否则池无法保证有足够的线程可用于确保进度或良好性能。

    等待完成和提取任务结果的主要方法是join() ,但有几种变体: Future.get()方法支持使用Future约定完成和报告结果的可中断和/或定时等待。 方法invoke()在语义上等效于fork(); join()但始终尝试在当前线程中开始执行。 这些方法的“ 安静 ”形式不会提取结果或报告异常。 当执行一组任务时,这些可能很有用,并且您需要延迟处理结果或异常,直到所有任务完成。 方法invokeAll (提供多个版本)执行最常见的并行调用形式:分叉一组任务并将它们全部连接起来。

    在最典型的用法中,fork-join对就像一个调用(fork),并从并行递归函数返回(join)。 与其他形式的递归调用一样,返回(连接)应该在最里面的第一个执行。 例如, a.fork(); b.fork(); b.join(); a.join();很可能是显着大于接合更有效a之前b

    可以在几个详细级别查询任务的执行状态: Future.isDone()如果任务以任何方式完成(包括未执行任务被取消的情况),则为真; 如果任务在没有取消或遇到异常的情况下完成, 则为isCompletedNormally() ; Future.isCancelled()如果任务被取消(在这种情况下是真实的getException()返回CancellationException ); 如果任务被取消或遇到异常,则isCompletedAbnormally()为真,在这种情况下, getException()将返回遇到的异常或CancellationException

    ForkJoinTask类通常不直接子类化。 相反,你继承了支持叉的特定风格/连接处理,通常是抽象类的一个RecursiveAction对于不返回结果大多数计算, RecursiveTask对于那些做的, CountedCompleter对于那些在已完成的操作触发其它动作。 通常,具体的ForkJoinTask子类声明包含其参数的字段,在构造函数中建立,然后定义以某种方式使用此基类提供的控制方法的compute方法。

    方法join()及其变体仅适用于完成依赖性为非循环的情况; 也就是说,并行计算可以描述为有向无环图(DAG)。 否则,执行可能会遇到一种形式的死锁,因为任务周期性地等待彼此。 然而,该框架支持的其它方法和技术(例如使用PhaserhelpQuiesce() ,和complete(V) ),其可以使用在构建定制子类为没有静态构造为DAG的问题。 为了支持这样的用途中,ForkJoinTask可以用原子标记short使用值setForkJoinTaskTag(short)compareAndSetForkJoinTaskTag(short, short) ,并使用托运getForkJoinTaskTag() ForkJoinTask实现不会出于任何目的使用这些protected方法或标记,但它们可能用于构造专用子类。 例如,并行图遍历可以使用提供的方法来避免重新访问已经处理的节点/任务。 (标记的方法名称很大,部分是为了鼓励定义反映其使用模式的方法。)

    大多数基本支持方法是final ,以防止覆盖与底层轻量级任务调度框架本质上相关的实现。 开发者创建新的基本样式叉/加入处理应最低限度地实现protected方法exec()setRawResult(V) ,和getRawResult() ,同时还引入,可以在其子类来实现的抽象计算方法,可能依赖于其他protected由此类提供的方法。

    ForkJoinTasks应该执行相对少量的计算。 应将大型任务拆分为较小的子任务,通常通过递归分解。 作为一个非常粗略的经验法则,任务应该执行超过100个且少于10000个基本计算步骤,并且应该避免无限循环。 如果任务太大,则并行性无法提高吞吐量。 如果太小,那么内存和内部任务维护开销可能会压倒处理。

    此类为RunnableCallable提供adapt方法,在将ForkJoinTasks执行与其他类型的任务混合时可能会有用。 当所有任务都是这种形式时,请考虑使用在asyncMode中构造的池。

    ForkJoinTasks是Serializable ,它使它们可以用于扩展,例如远程执行框架。 在执行之前或之后但不执行期间序列化任务是明智的。 执行过程中不依赖序列化。

    从以下版本开始:
    1.7
    另请参见:
    Serialized Form
    • 构造方法摘要

      构造方法  
      构造器 描述
      ForkJoinTask()  
    • 方法摘要

      所有方法  静态方法  实例方法 抽象方法  具体的方法 
      变量和类型 方法 描述
      static ForkJoinTask<?> adapt​(Runnable runnable)
      返回一个新的 ForkJoinTask ,它执行给定 Runnablerun方法作为其操作,并在 join()返回null结果。
      static <T> ForkJoinTask<T> adapt​(Runnable runnable, T result)
      返回一个新的 ForkJoinTask ,它执行给定 Runnablerun方法作为其操作,并返回给定结果 join()
      static <T> ForkJoinTask<T> adapt​(Callable<? extends T> callable)
      返回一个新的 ForkJoinTask ,它执行给定 Callablecall方法作为其操作,并在 join()返回其结果,将遇到的任何已检查异常转换为 RuntimeException
      boolean cancel​(boolean mayInterruptIfRunning)
      尝试取消执行此任务。
      boolean compareAndSetForkJoinTaskTag​(short expect, short update)
      以原子方式有条件地为此任务设置标记值。
      void complete​(V value)
      完成此任务,如果尚未中止或取消,则返回给定值作为后续调用 join和相关操作的结果。
      void completeExceptionally​(Throwable ex)
      异常完成此任务,如果尚未中止或取消,则会导致它在 join和相关操作上抛出给定的异常。
      protected abstract boolean exec()
      立即执行此任务的基本操作,如果从此方法返回后,此任务保证正常完成,则返回true。
      ForkJoinTask<V> fork()
      安排在当前任务运行的池中异步执行此任务(如果适用),或者使用 ForkJoinPool.commonPool()如果不是 inForkJoinPool()
      V get()
      如果需要等待计算完成,然后检索其结果。
      V get​(long timeout, TimeUnit unit)
      如果需要,最多等待计算完成的给定时间,然后检索其结果(如果可用)。
      Throwable getException()
      返回由基础计算抛出的异常,或 CancellationException取消,如果,或 null如果没有,或者如果方法尚未完成。
      short getForkJoinTaskTag()
      返回此任务的标记。
      static ForkJoinPool getPool()
      返回托管当前线程的池,如果当前线程在任何ForkJoinPool之外执行,则返回 null
      static int getQueuedTaskCount()
      返回当前工作线程已分叉但尚未执行的任务数的估计值。
      abstract V getRawResult()
      返回 join()返回的结果,即使此任务异常完成,也可以返回 null如果此任务未完成)。
      static int getSurplusQueuedTaskCount()
      返回当前工作线程保留的本地排队任务数量的估计值,而不是其他可能窃取它们的工作线程,或者如果此线程未在ForkJoinPool中运行则返回零。
      static void helpQuiesce()
      可能执行任务,直到托管当前任务的池 is quiescent
      static boolean inForkJoinPool()
      返回true如果当前线程是ForkJoinWorkerThread执行作为ForkJoinPool计算。
      V invoke()
      开始执行此任务,必要时等待其完成,并返回其结果,或者如果基础计算这样做,则抛出(未选中) RuntimeExceptionError
      static <T extends ForkJoinTask<?>>
      Collection<T>
      invokeAll​(Collection<T> tasks)
      isDone指定集合中的所有任务,当 isDone为每个任务保留或者遇到(未经检查的)异常时返回,在这种情况下重新抛出异常。
      static void invokeAll​(ForkJoinTask<?>... tasks)
      isDone给定的任务,当每个任务保持 isDone或者遇到(未经检查的)异常时返回,在这种情况下重新抛出异常。
      static void invokeAll​(ForkJoinTask<?> t1, ForkJoinTask<?> t2)
      isDone给定的任务,当 isDone为每个任务保留或者遇到(未经检查的)异常时返回,在这种情况下重新抛出异常。
      boolean isCompletedAbnormally()
      如果此任务引发异常或已取消,则返回 true
      boolean isCompletedNormally()
      如果此任务完成但未抛出异常且未取消,则返回 true
      V join()
      返回 is done时的计算结果。
      protected static ForkJoinTask<?> peekNextLocalTask()
      返回但不取消计划或执行当前线程排队但尚未执行的任务(如果一个可立即可用)。
      protected static ForkJoinTask<?> pollNextLocalTask()
      如果当前线程在ForkJoinPool中运行,则取消计划并返回,而不执行当前线程排队但尚未执行的下一个任务。
      protected static ForkJoinTask<?> pollSubmission()
      如果当前线程在ForkJoinPool中运行,则在不执行的情况下取消计划并返回外部提交到池的任务(如果有)。
      protected static ForkJoinTask<?> pollTask()
      如果当前线程在ForkJoinPool中运行,则取消计划并返回,而不执行,由当前线程排队但尚未执行的下一个任务,如果有可用,或者如果不可用,则由其他某个线程分叉的任务,如果可供使用的话。
      void quietlyComplete()
      通常在不设置值的情况下完成此任务。
      void quietlyInvoke()
      开始执行此任务并在必要时等待其完成,而不返回其结果或抛出异常。
      void quietlyJoin()
      加入此任务,而不返回其结果或抛出异常。
      void reinitialize()
      重置此任务的内部簿记状态,允许后续 fork
      short setForkJoinTaskTag​(short newValue)
      以原子方式设置此任务的标记值并返回旧值。
      protected abstract void setRawResult​(V value)
      强制返回给定值作为结果。
      boolean tryUnfork()
      尝试取消计划执行此任务。
    • 构造方法详细信息

      • ForkJoinTask

        public ForkJoinTask()
    • 方法详细信息

      • fork

        public final ForkJoinTask<V> fork()
        安排在当前任务运行的池中异步执行此任务(如果适用),或者使用ForkJoinPool.commonPool()如果不是inForkJoinPool() 虽然不一定强制执行,但是除非已完成并重新初始化任务,否则多次分叉任务是一个使用错误。 对该任务的状态或其操作的任何数据的后续修改不一定由除执行它之外的任何线程一致地观察,除非先前调用join()或相关方法,或者调用Future.isDone()返回true
        结果
        this ,简化用法
      • join

        public final V join()
        返回is done时的计算结果。 此方法与get()不同之处在于异常完成导致RuntimeExceptionError ,而不是ExecutionException ,并且调用线程的中断不会导致该方法通过抛出InterruptedException而突然返回。
        结果
        计算结果
      • invoke

        public final V invoke()
        开始执行此任务,必要时等待其完成,并返回其结果,或者如果基础计算这样做,则抛出(未选中) RuntimeExceptionError
        结果
        计算结果
      • invokeAll

        public static void invokeAll​(ForkJoinTask<?> t1,                             ForkJoinTask<?> t2)
        isDone给定的任务,当isDone为每个任务保留或者遇到(未经检查的)异常时返回,在这种情况下重新抛出异常。 如果多个任务遇到异常,则此方法会抛出任何一个异常。 如果任何任务遇到异常,则另一个任务可能会被取消。 但是,在特殊退货时无法保证个别任务的执行状态。 可以使用getException()和相关方法获取每个任务的状态,以检查它们是否已被取消,正常完成或异常完成,或者未处理。
        参数
        t1 - 第一项任务
        t2 - 第二项任务
        异常
        NullPointerException - 如果任何任务为空
      • invokeAll

        public static void invokeAll​(ForkJoinTask<?>... tasks)
        isDone给定的任务,当isDone为每个任务保留或者遇到(未经检查的)异常时返回,在这种情况下重新抛出异常。 如果多个任务遇到异常,则此方法会抛出任何一个异常。 如果任何任务遇到异常,则可能会取消其他任务。 但是,在特殊退货时无法保证个别任务的执行状态。 可以使用getException()和相关方法获取每个任务的状态,以检查它们是否已被取消,正常完成或异常完成,或者未处理。
        参数
        tasks - 任务
        异常
        NullPointerException - 如果任何任务为空
      • invokeAll

        public static <T extends ForkJoinTask<?>> Collection<T> invokeAll​(Collection<T> tasks)
        isDone指定集合中的所有任务,当isDone为每个任务保留或者遇到(未经检查的)异常时返回,在这种情况下重新抛出异常。 如果多个任务遇到异常,则此方法会抛出任何一个异常。 如果任何任务遇到异常,则可能会取消其他任务。 但是,在特殊退货时无法保证个别任务的执行状态。 可以使用getException()和相关方法获取每个任务的状态,以检查它们是否已被取消,正常完成或异常完成,或者未处理。
        参数类型
        T - 从任务返回的值的类型
        参数
        tasks - 任务集合
        结果
        任务参数,以简化使用
        异常
        NullPointerException - 如果任务或任何元素为null
      • cancel

        public boolean cancel​(boolean mayInterruptIfRunning)
        尝试取消执行此任务。 如果任务已经完成或由于某些其他原因无法取消,则此尝试将失败。 如果成功,并且在cancel时此任务尚未启动,则禁止执行此任务。 经过此方法成功返回,除非有介入呼叫reinitialize() ,后续调用到Future.isCancelled()Future.isDone()cancel将返回true ,并呼吁join() ,并会导致相关方法CancellationException

        可以在子类中重写此方法,但如果是这样,仍必须确保这些属性成立。 特别是, cancel方法本身不能抛出异常。

        此方法旨在由其他任务调用。 要终止当前任务,您只需从其计算方法返回或抛出未经检查的异常,或调用completeExceptionally(Throwable)

        Specified by:
        cancel在界面 Future<V>
        参数
        mayInterruptIfRunning - 此值在默认实现中无效,因为中断不用于控制取消。
        结果
        true如果此任务现已取消
      • isCompletedAbnormally

        public final boolean isCompletedAbnormally()
        如果此任务引发异常或已取消,则返回 true
        结果
        true如果此任务引发异常或被取消
      • isCompletedNormally

        public final boolean isCompletedNormally()
        如果此任务完成但未抛出异常且未取消,则返回 true
        结果
        true如果此任务完成而没有抛出异常且未被取消
      • getException

        public final Throwable getException()
        返回由基础计算抛出的异常,或 CancellationException取消,如果,或 null如果没有,或者如果方法尚未完成。
        结果
        例外,如果没有, null
      • completeExceptionally

        public void completeExceptionally​(Throwable ex)
        异常完成此任务,如果尚未中止或取消,则会导致它在join和相关操作上抛出给定异常。 此方法可用于在异步任务中引发异常,或强制完成无法完成的任务。 不鼓励在其他情况下使用它。 此方法是可覆盖的,但重写的版本必须调用super实现以维护保证。
        参数
        ex - 抛出异常。 如果此异常不是RuntimeExceptionError ,则抛出的实际异常将是RuntimeException ,原因ex
      • complete

        public void complete​(V value)
        完成此任务,如果尚未中止或取消,则返回给定值作为后续调用join和相关操作的结果。 此方法可用于为异步任务提供结果,或为无法正常完成的任务提供替代处理。 不鼓励在其他情况下使用它。 此方法是可覆盖的,但重写的版本必须调用super实现以维护保证。
        参数
        value - 此任务的结果值
      • quietlyComplete

        public final void quietlyComplete()
        通常在不设置值的情况下完成此任务。 setRawResult(V) (默认为null )建立的最新值将作为后续调用join及相关操作的结果返回。
        从以下版本开始:
        1.8
      • quietlyJoin

        public final void quietlyJoin()
        加入此任务,而不返回其结果或抛出异常。 当某些任务已被取消或已知已中止时,此方法在处理任务集合时可能很有用。
      • quietlyInvoke

        public final void quietlyInvoke()
        开始执行此任务并在必要时等待其完成,而不返回其结果或抛出异常。
      • helpQuiesce

        public static void helpQuiesce()
        可能执行任务,直到托管当前任务的池is quiescent 此方法可用于分叉许多任务的设计中,但没有显式连接,而是执行它们直到所有任务都被处理。
      • reinitialize

        public void reinitialize()
        重置此任务的内部簿记状态,允许后续fork 此方法允许重复使用此任务,但仅当此任务从未分叉,或已分叉,然后已完成且此任务的所有未完成联接也已完成时,才会重用。 不保证在任何其他使用条件下的效果。 当在循环中执行预先构造的子任务树时,该方法可能是有用的。

        完成此方法后, isDone()报告false ,和getException()报告null 但是, getRawResult返回的值不受影响。 要清除此值,可以调用setRawResult(null)

      • getPool

        public static ForkJoinPool getPool()
        返回托管当前线程的池,如果当前线程在任何ForkJoinPool之外执行,则返回null

        该方法返回null当且仅当inForkJoinPool()回报false

        结果
        游泳池,如果没有, null
      • inForkJoinPool

        public static boolean inForkJoinPool()
        返回true如果当前线程是ForkJoinWorkerThread执行作为ForkJoinPool计算。
        结果
        true如果当前线程是作为ForkJoinPool计算执行的ForkJoinWorkerThread ,否则为false
      • tryUnfork

        public boolean tryUnfork()
        尝试取消计划执行此任务。 如果此任务是当前线程最近分叉的任务,并且尚未在另一个线程中开始执行,则此方法通常(但不保证)成功。 在安排可能已经但未被盗的任务的替代本地处理时,此方法可能很有用。
        结果
        true如果不成功
      • getQueuedTaskCount

        public static int getQueuedTaskCount()
        返回当前工作线程已分叉但尚未执行的任务数的估计值。 此值可能对于是否分叉其他任务的启发式决策很有用。
        结果
        任务数量
      • getSurplusQueuedTaskCount

        public static int getSurplusQueuedTaskCount()
        返回当前工作线程保留的本地排队任务数量的估计值,而不是其他可能窃取它们的工作线程,或者如果此线程未在ForkJoinPool中运行则返回零。 此值可能对于是否分叉其他任务的启发式决策很有用。 在ForkJoinTasks的许多用法中,在稳定状态下,每个工作者应该致力于维持小的恒定剩余(例如,3)任务,并且如果超过该阈值则在本地处理计算。
        结果
        剩余的任务数量可能是负数
      • getRawResult

        public abstract V getRawResult()
        返回join()返回的结果,即使此任务异常完成,也可以返回null如果此任务未完成)。 此方法旨在帮助调试以及支持扩展。 不鼓励在任何其他环境中使用它。
        结果
        结果,如果没有完成, null
      • setRawResult

        protected abstract void setRawResult​(V value)
        强制返回给定值作为结果。 此方法旨在支持扩展,通常不应该以其他方式调用。
        参数
        value - 该值
      • exec

        protected abstract boolean exec()
        立即执行此任务的基本操作,如果从此方法返回后,此任务保证正常完成,则返回true。 否则,此方法可能返回false,以指示此任务未必完成(或未知是完整的),例如在需要显式调用完成方法的异步操作中。 此方法还可能抛出(未经检查的)异常以指示异常退出。 此方法旨在支持扩展,通常不应该以其他方式调用。
        结果
        true如果已知此任务已正常完成
      • peekNextLocalTask

        protected static ForkJoinTask<?> peekNextLocalTask()
        返回但不取消计划或执行当前线程排队但尚未执行的任务(如果一个可立即可用)。 无法保证此任务实际上将被轮询或执行。 相反,即使存在任务但是在没有与其他线程争用的情况下也无法访问此方法,此方法可能返回null。 此方法主要用于支持扩展,否则不太可能有用。
        结果
        下一个任务,如果没有, null
      • pollNextLocalTask

        protected static ForkJoinTask<?> pollNextLocalTask()
        如果当前线程在ForkJoinPool中运行,则取消计划并返回,而不执行当前线程排队但尚未执行的下一个任务。 此方法主要用于支持扩展,否则不太可能有用。
        结果
        下一个任务,如果没有, null
      • pollTask

        protected static ForkJoinTask<?> pollTask()
        如果当前线程在ForkJoinPool中运行,则取消计划并返回,而不执行,由当前线程排队但尚未执行的下一个任务,如果有可用,或者如果不可用,则由其他某个线程分叉的任务,如果可供使用的话。 可用性可能是暂时的,因此null结果并不一定意味着此任务正在运行的池的静止。此方法主要用于支持扩展,否则不太可能有用。
        结果
        任务,或 null如果没有)
      • pollSubmission

        protected static ForkJoinTask<?> pollSubmission()
        如果当前线程在ForkJoinPool中运行,则在不执行的情况下取消计划并返回外部提交到池的任务(如果有)。 可用性可能是暂时的,因此null结果并不一定意味着池的静止。 此方法主要用于支持扩展,否则不太可能有用。
        结果
        任务,或 null如果没有)
        从以下版本开始:
        9
      • getForkJoinTaskTag

        public final short getForkJoinTaskTag()
        返回此任务的标记。
        结果
        此任务的标记
        从以下版本开始:
        1.8
      • setForkJoinTaskTag

        public final short setForkJoinTaskTag​(short newValue)
        以原子方式设置此任务的标记值并返回旧值。
        参数
        newValue - 新标记值
        结果
        标签的先前值
        从以下版本开始:
        1.8
      • compareAndSetForkJoinTaskTag

        public final boolean compareAndSetForkJoinTaskTag​(short expect,                                                  short update)
        以原子方式有条件地为此任务设置标记值。 在其他应用程序中,标签可以用作在图上操作的任务中的访问标记,如在处理之前检查: if (task.compareAndSetForkJoinTaskTag((short)0, (short)1))方法,否则因为节点已被访问而退出。
        参数
        expect - 期望的标记值
        update - 新标签值
        结果
        如果成功true ; 即,当前值等于expect并更改为update
        从以下版本开始:
        1.8
      • adapt

        public static ForkJoinTask<?> adapt​(Runnable runnable)
        返回一个新的 ForkJoinTask ,它执行给定 Runnablerun方法作为其操作,并在 join()返回null结果。
        参数
        runnable - 可运行的动作
        结果
        任务
      • adapt

        public static <T> ForkJoinTask<T> adapt​(Runnable runnable,                                        T result)
        返回一个新的 ForkJoinTask ,它执行给定 Runnablerun方法作为其操作,并返回给定结果 join()
        参数类型
        T - 结果的类型
        参数
        runnable - 可运行的动作
        result - 完成后的结果
        结果
        任务
      • adapt

        public static <T> ForkJoinTask<T> adapt​(Callable<? extends T> callable)
        返回一个新的 ForkJoinTask ,它执行给定 Callablecall方法作为其操作,并在 join()返回其结果,将遇到的任何已检查异常转换为 RuntimeException
        参数类型
        T - 可调用结果的类型
        参数
        callable - 可调用的操作
        结果
        任务