Java多线程 Future和FutureTask的区别

简介: Java多线程 Future和FutureTask的区别

一、说明


Future和FutureTask的关系


  • Future 是一个接口,无法直接创建对象,需配合线程池使用.submit()方法返回值Future来保存执行结果;而使用.execute()方法传入Runnable接口无返回值


  • FutureTask 是一个类,可以直接创建对象,其实现了RunnableFuture接口(继承Future接口)


使用区别


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


二、理解


Future


  • java.util.concurrent包下Future<V>接口,对RunnableCallable对象执行任务完成后获取执行结果


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可处于以下三种行状态



FutureTask方法执行示意图


  • .cancel(ture)会中断线程停止任务,适用于长时间处于运行的任务,并且能够处理interruption


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



三、实现


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("主线程执行完成");
    }
}



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("主线程执行完成");
    }
}


目录
相关文章
|
1月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
121 1
|
1月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
137 1
|
2月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
124 0
|
2月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
193 16
|
3月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
3月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践
|
4月前
|
Java API 调度
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
345 83
|
4月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
189 0