并发编程之五FutureTask

news/2025/1/11 8:52:48/

futureTask实现了Runnable, Future接口,Future接口有如下定义:

    /*** 取消任务,如果任务已经在执行,mayInterruptIfRunning为true,则* 向执行线程发送interrupt事件,否则任由任务执行完毕。* 返回值为是否取消成功*/boolean cancel(boolean mayInterruptIfRunning);// 任务是否已经被取消boolean isCancelled();// 任务是否已经执行完毕boolean isDone();/** * 等待并获取结果,会抛出以下异常* 1. CancellationException 任务被取消* 2. ExecutionException 任务执行异常* 3. InterruptedException 执行线程在等待时收到interrupted事件*/V get() throws InterruptedException, ExecutionException;/*** Waits if necessary for at most the given time for the computation* to complete, and then retrieves its result, if available.** @param timeout the maximum time to wait* @param unit the time unit of the timeout argument* @return the computed result* @throws CancellationException if the computation was cancelled* @throws ExecutionException if the computation threw an* exception* @throws InterruptedException if the current thread was interrupted* while waiting* @throws TimeoutException if the wait timed out*//** * 等待并获取结果,timeout是最大等待时间,会抛出以下异常* 1. CancellationException 任务被取消* 2. ExecutionException 任务执行异常* 3. InterruptedException 执行线程在等待时收到interrupted事件* 4. 等待超时*/V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;

1. isDone示例

package org.example.concurrent;import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.Test;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;import static org.assertj.core.api.Assertions.assertThat;@Slf4j
public class FutureTaskTest {private final ExecutorService executorService = Executors.newSingleThreadExecutor();@Testpublic void test() {FutureTask<String> futureTask = new FutureTask<>(() -> {log.debug("futureTask running");return "ok";});// 提交线程池之前,futureTask的状态为未执行assertThat(futureTask).isNotDone();executorService.execute(futureTask);// 等待100ms后,执行成功assertThat(futureTask).succeedsWithin(100L, TimeUnit.MILLISECONDS, InstanceOfAssertFactories.STRING).contains("ok");}
}

2. cancel和 isCancelled

2.1 任务执行前cancel

示例:

package org.example.concurrent;import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;@Slf4j
public class FutureTaskTest {private final ExecutorService executorService = Executors.newSingleThreadExecutor();@Testpublic void test() {FutureTask<String> futureTask = new FutureTask<>(() -> {log.debug("futureTask running");return "ok";});// 任务执行前cancelfutureTask.cancel(false);assertThat(futureTask).isCancelled().isNotDone();executorService.execute(futureTask);// 取消的任务get会报取消异常assertThatExceptionOfType(CancellationException.class).isThrownBy(futureTask::get);// get后futureTask变为isDone;assertThat(futureTask).isCancelled().isDone();}
}

2.2 任务执行中取消任务

    示例1:取消,不通知任务线程中断

package org.example.concurrent;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.*;import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;@Slf4j
public class FutureTaskTest {private final ExecutorService executorService = Executors.newSingleThreadExecutor();@SneakyThrows@Testpublic void test() {FutureTask<String> futureTask = new FutureTask<>(() -> {log.debug("futureTask start");sleep(300L);log.debug("futureTask end");return "ok";});executorService.execute(futureTask);// 等待100毫秒,此时futureTask正在运行, 然后取消任务sleep(100L);futureTask.cancel(false);// 取消的任务get会报取消异常assertThatExceptionOfType(CancellationException.class).isThrownBy(futureTask::get);// get后futureTask变为isDone;assertThat(futureTask).isCancelled().isDone();// 继续等待1秒,会发现任务会执行完毕sleep(1000L);}@SneakyThrowsprivate void sleep(long delay) {TimeUnit.MILLISECONDS.sleep(delay);}
}

执行日志:

11:53:58.340 [pool-1-thread-1] DEBUG o.example.concurrent.FutureTaskTest - futureTask start
11:53:58.649 [pool-1-thread-1] DEBUG o.example.concurrent.FutureTaskTest - futureTask end

示例2:取消并通知任务线程中断(如果线程处于阻塞中,会感知到自身中断)

package org.example.concurrent;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.*;import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;@Slf4j
public class FutureTaskTest {private final ExecutorService executorService = Executors.newSingleThreadExecutor();@SneakyThrows@Testpublic void test() {FutureTask<String> futureTask = new FutureTask<>(() -> {log.debug("futureTask start");try {sleep(300L);} catch (Exception e) {// 捕获打印异常名称并重新抛出log.error("catch Exception:{}", e.getClass().getSimpleName());throw e;}log.debug("futureTask end");return "ok";});executorService.execute(futureTask);// 等待100毫秒,此时futureTask正在运行, 然后取消任务sleep(100L);futureTask.cancel(true);// 取消的任务get会报取消异常assertThatExceptionOfType(CancellationException.class).isThrownBy(futureTask::get);// get后futureTask变为isDone;assertThat(futureTask).isCancelled().isDone();// 继续等待1秒,会发现任务会执行完毕sleep(1000L);}@SneakyThrowsprivate void sleep(long delay) {TimeUnit.MILLISECONDS.sleep(delay);}
}

执行过程中,futureTask执行线程处于休眠中,能够感知到线程中断,执行结果如下:

11:59:10.410 [pool-1-thread-1] DEBUG o.example.concurrent.FutureTaskTest - futureTask start
11:59:10.513 [pool-1-thread-1] ERROR o.example.concurrent.FutureTaskTest - catch Exception:InterruptedException
11:59:10.515 [pool-1-thread-1] DEBUG o.example.concurrent.FutureTaskTest - futureTask end

示例3:重复取消任务,会取消失败

package org.example.concurrent;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.*;import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;@Slf4j
public class FutureTaskTest {private final ExecutorService executorService = Executors.newSingleThreadExecutor();@SneakyThrows@Testpublic void test() {FutureTask<String> futureTask = new FutureTask<>(() -> {log.debug("futureTask start");sleep(300L);log.debug("futureTask end");return "ok";});executorService.execute(futureTask);// 等待100毫秒,sleep(100L);// 此时futureTask正在运行, 然后取消任务, 如果重复取消,会返回失败assertThat(futureTask.cancel(false)).isTrue();assertThat(futureTask.cancel(false)).isFalse();// 取消的任务get会报取消异常assertThatExceptionOfType(CancellationException.class).isThrownBy(futureTask::get);}@SneakyThrowsprivate void sleep(long delay) {TimeUnit.MILLISECONDS.sleep(delay);}
}

2.3 任务执行完成后cancel

        任务执行完毕后在取消任务执行,取消动作会失败。参考下面的代码:

package org.example.concurrent;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.Test;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;import static org.assertj.core.api.Assertions.assertThat;@Slf4j
public class FutureTaskTest {private final ExecutorService executorService = Executors.newSingleThreadExecutor();@SneakyThrows@Testpublic void test() {FutureTask<String> futureTask = new FutureTask<>(() -> {log.debug("futureTask start");log.debug("futureTask end");return "ok";});executorService.execute(futureTask);// 等待100毫秒,此时futureTask已经执行完毕, 取消任务执行会失败sleep(100L);assertThat(futureTask.cancel(true)).isFalse();// 判断执行成功assertThat(futureTask).succeedsWithin(0L, TimeUnit.MILLISECONDS, InstanceOfAssertFactories.STRING).contains("ok");}@SneakyThrowsprivate void sleep(long delay) {TimeUnit.MILLISECONDS.sleep(delay);}
}

3. get等待指定时间

get指定最大等待时间,如果超出此时间,则会抛出TimeoutException异常:

package org.example.concurrent;import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.concurrent.*;import static org.assertj.core.api.Assertions.assertThatExceptionOfType;@Slf4j
public class FutureTaskTest {private final ExecutorService executorService = Executors.newSingleThreadExecutor();@SneakyThrows@Testpublic void test() {FutureTask<String> futureTask = new FutureTask<>(() -> {log.debug("futureTask start");sleep(1000L);log.debug("futureTask end");return "ok";});executorService.execute(futureTask);// get等待10毫秒,由于futureTask会执行1秒钟,get会报超时异常assertThatExceptionOfType(TimeoutException.class).isThrownBy(() -> futureTask.get(10L, TimeUnit.MILLISECONDS));}@SneakyThrowsprivate void sleep(long delay) {TimeUnit.MILLISECONDS.sleep(delay);}
}


http://www.ppmy.cn/news/47177.html

相关文章

VMware开机自启虚拟机系统

一、前提 wmware开机自启&#xff0c;安装完毕wmware不用管&#xff0c;默认该软件以及相关服务就是开机自启准备waware虚拟机&#xff08;一般都linux&#xff0c;我用centos7&#xff0c;你随意&#xff09; 二、脚本 脚本命令如下&#xff0c;等待30秒&#xff08;给服务自启…

计算机组成原理——第五章中央处理器(上)

半生风雨半生伤&#xff0c;半醉半醒半心凉 文章目录 前言5.1 CPU的功能和基本结构5.2 指令周期的数据流5.3.1 单总线结构5.3.2 专用通路结构 前言 之前我们就说过CPU主要包括两个部分&#xff0c;运算器和控制器&#xff0c;运算器主要是实现算数运算.逻辑运算&#xff0c; 运…

Memory Analyzer Mat

目录 一、JDK 、JRE和JVM 的关系 二、Java进程内存占用查询命令 2.1JAVA 代码是如何执行的 2.2何时用hrpof文件分析内存 三、Memory Analyzer Mat 3.1Memory Analyzer Mat安装 3.2 Overview视图 3.2.1直方图视图&#xff08;histogram&#xff09; 3.2.2 Dominator Tr…

字典树p8036

Description 给定 &#xfffd;n 个模式串 &#xfffd;1,&#xfffd;2,…,&#xfffd;&#xfffd;s1​,s2​,…,sn​ 和 &#xfffd;q 次询问&#xff0c;每次询问给定一个文本串 &#xfffd;&#xfffd;ti​&#xff0c;请回答 &#xfffd;1∼&#xfffd;&#xfff…

NetSuite GPT的辅助编程实践

作为GPT综合症的一种表现&#xff0c;我们今朝来探究下GPT会不会抢了我们SuiteScript的编程饭碗&#xff0c;以及如何与之相处。以下内容来自我个人的实践总结。 我们假设一个功能场景&#xff1a; 为了让用户能够在报价单上实现“一键多行”功能&#xff0c;也就是在报价中可…

learn_C_deep_1 (C程序补充知识、变量的声明和定义、声明和定义的区别)

目录 C程序补充知识 变量的声明和定义 1.什么是变量&#xff1f; 2.变量的本质是什么&#xff1f; - 所有的变量都要在内存的某个位置开辟空间 3.变量的定义和声明形式、初始化和赋值的区别 4.为什么要定义变量 声明和定义的区别 C程序补充知识 先让我们来看一段C语言…

.net学习教程大纲

以下是一个 .NET 学习指南大纲&#xff0c;供您参考&#xff1a; 一、C# 编程语言 语言基础知识 数据类型、变量、常量 运算符、表达式 流程控制语句 数组、集合和泛型 类、对象、封装、继承和多态 接口和委托 异常处理 LINQ 面向对象设计原则 二、.NET 框架 .NET…

激活函数(Activation Function)及十大常见激活函数

目录 1 激活函数的概念和作用 1.1 激活函数的概念 1.2 激活函数的作用 1.3 通俗地理解一下激活函数&#xff08;图文结合&#xff09; 1.3.1 无激活函数的神经网络 1.3.2 带激活函数的神经网络 2 神经网络梯度消失与梯度爆炸 2.1 简介梯度消失与梯度爆炸 2.2 梯度不稳…