首页 > 编程语言 >Java多线程 Future和FutureTask的区别

Java多线程 Future和FutureTask的区别

时间:2022-11-11 10:32:44浏览次数:45  
标签:多线程 Java System println Future 线程 FutureTask 执行


目录

  • ​​一、说明​​
  • ​​二、理解​​
  • ​​三、实现​​
  • ​​1.实现接口​​
  • ​​2.使用Future​​
  • ​​3.使用FutureTask​​

一、说明

Future和FutureTask的关系

  • Future 是一个接口,无法直接创建对象,需配合线程池使用​​.submit()​​​方法返回值​​Future​​​来保存执行结果;而使用​​.execute()​​​方法传入​​Runnable​​接口无返回值
  • FutureTask 是一个类,可以直接创建对象,其实现了​​RunnableFuture​​​接口(继承​​Future​​接口)

使用区别

  • 就是一个接口和实现类的不同写法

二、理解

Future

  • ​java.util.concurrent​​​包下​​Future<V>​​​接口,对​​Runnable​​​或​​Callable​​对象执行任务完成后获取执行结果
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
  • ​mayInterruptRunning​​ 表示是否中断执行中的线程
  • ​boolean cancel()​​ 尝试取消任务的执行,如果任务已经完成或已被取消,则返回false;如果任务已经启动,将以中断执行线程的方式停止该任务,停止成功则返回true
  • ​boolean isDone()​​若任务完成,则返回true
  • ​boolean isCancelled()​​ 若任务在完成前取消,则返回true
  • ​get()​​ 获取执行结果,必须等待任务完成后才返回结果
  • ​get(long timeout, TimeUnit unit)​​ 获取执行结果,timeout表示等待的最长时间,unit表示时间单位,在指定时间内还没获取到结果,则返回null

FutureTask

  • ​java.util.concurrent​​​包下实现​​RunnableFuture<V>​​​接口,可实现​​Runnable​​​接口执行线程,也可实现​​Future​​接口获取执行结果
public class FutureTask<V> implements RunnableFuture<V> {
……
}
  • ​RunnableFuture​​​接口继承​​Runnable​
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}

FutureTask执行状态

  • 根据方法执行的时机,FutureTask可处于以下三种行状态

Java多线程 Future和FutureTask的区别_线程池

FutureTask方法执行示意图

  • ​.cancel(ture)​​会中断线程停止任务,适用于长时间处于运行的任务,并且能够处理interruption
  • ​.cancel(false)​​会让线程正常执行至完成,并返回false,适用于未能处理interruption的任务,或者不清楚是否支持取消的任务,以及等待已经开始的任务执行完成

Java多线程 Future和FutureTask的区别_主线程_02

三、实现

1.实现接口

创建​​CallableThreadDemo​​​类实现​​Callable​​接口

public class CallableThreadDemo implements Callable{
@Override
public String call() throws Exception {
System.out.println("Callable子线程: " +Thread.currentThread().getName()+ " 开启");
return "我是Callable子线程: " +Thread.currentThread().getName()+ " 产生的结果";
}
}

2.使用Future

创建​​CallableTest​​​类执行测试,将创建好的线程对象通过​​.submit()​​​方法提交到线程池去执行,线程执行后,返回值​​Future​​可被拿到

public class CallableTest {
public static void main(String[] args) {
// 1.创建线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 2.创建Callable子线程对象任务
CallableThreadDemo callableThread_1 = new CallableThreadDemo();
// 3.提交任务到线程池
Future future = executorService.submit(callableThread_1);
// 4.获取执行结果
try {
System.out.println("主线程开始执行");

System.out.println("主线程要取得Callable子线程的结果");
if (future.get()!=null){
//输出获取的结果
System.out.println(future.get());
}else {
//输出未获取到结果
System.out.println("future.get()未获取到结果");
}
} catch (InterruptedException e){
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
// 5.关闭线程池
executorService.shutdown();
System.out.println("主线程执行完成");
}
}

Java多线程 Future和FutureTask的区别_线程池_03

3.使用FutureTask

创建​​FutureTask​​​对象,提交任务到线程池,可以交给​​Executor​​​执行,或将创建好的线程对象通过​​.submit()​​​方法提交到线程池去执行,线程执行后,返回值​​FutureTask​​可被拿到

public class CallableTest {
public static void main(String[] args) {
// 1.创建线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 2.创建Callable子线程对象任务
CallableThreadDemo callableThread_1 = new CallableThreadDemo();
// 3.提交任务到线程池
FutureTask futureTask = new FutureTask(callableThread_1);
executorService.submit(futureTask);
// 4.获取执行结果
try {
System.out.println("主线程开始执行");

System.out.println("主线程要取得Callable子线程的结果");
if (futureTask.get()!=null){
//输出获取的结果
System.out.println(futureTask.get());
}else {
//输出未获取到结果
System.out.println("futureTask.get()未获取到结果");
}
} catch (InterruptedException e){
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
// 5.关闭线程池
executorService.shutdown();
System.out.println("主线程执行完成");
}
}

Java多线程 Future和FutureTask的区别_java_04


标签:多线程,Java,System,println,Future,线程,FutureTask,执行
From: https://blog.51cto.com/u_15872973/5843056

相关文章

  • Java多线程 ThreadPoolExecutor-RejectedExecutionHandler拒绝执行策略
    目录​​一、说明​​​​二、理解​​​​三、实现​​​​1.AbortPolicy​​​​2.DiscardPolicy​​​​3.DiscardOldestPolicy​​​​4.CallerRunsPolicy​​​​5.自......
  • Java多线程 线程池Executor框架
    目录​​一、说明​​​​二、理解​​​​Executor​​​​ExecutorService​​​​Executors​​​​三、实现​​​​1.newSingleThreadExecutor​​​​2.newFixedThr......
  • 8:Spring MVC-Java Spring
    目录​​8.1WEB开发模式一​​​​8.2WEB开发模式二​​​​8.3SpringMVC介绍​​​​8.4SpringMVC主要组件​​​​8.5SpringMVC处理流程​​​​8.6SpringMVC的......
  • Java Web项目中使用RSA加密数据
    在Web项目中有些时候需要对传输的数据加密后再传输到服务端进行解密使用,这里采用RSA进行公钥加密私钥解密的模式会有较高的安全性。这里选用的工具库是 JSEncrypt.js ......
  • 硬核剖析Java锁底层AQS源码,深入理解底层架构设计
    我们常见的并发锁ReentrantLock、CountDownLatch、Semaphore、CyclicBarrier都是基于AQS实现的,所以说不懂AQS实现原理的,就不能说了解Java锁。上篇文章讲了AQS的加锁流程,这......
  • Java并发编程——基础知识(一)
    1.进程与线程1.1基本概念进程:对运行时程序的封装,是系统进行资源调度和分配的的基本单位,实现了操作系统的并发线程:进程的子任务,是CPU调度和分派的基本单位,用于保证程序......
  • Java组合异步编程(2)
    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~ 多数码农在开发的时候,要么处理同步应用,要么处理异步。但是如果能学会使用CompletableFuture,就会具备一种神奇的能力:将同......
  • 定位java程序中占用cpu最高的线程堆栈信息
    找出占用cpu最高的线程堆栈信息在java编码中,有时会因为粗心导致cpu占用较高的情况,为了避免影响程序的正常运行,需要找到问题并解决。这里模拟一个cpu占用较高的场景,并尝试......
  • Java MAC环境Intellij2022配置Servlet和Tomcat
    1、下载安装Tomcat官网:https://tomcat.apache.org/download-90.cgi ->download 下载完放入自定义路径,需要记住!这样算下载好了,详细-> https://blog.csdn.net/qq_44......
  • java学习
    Mardown学习标题:#空格+标题名字几级标题几个#字体Hello,word!Hello,word!Hello,word!Hello,word!Hello,word!引用12345>直接输入引用内容分割线___三个......