Future接口的优缺点

简介: JUC学习

Future接口的优缺点

优点

future+线程池异步多线程任务配合,能显著提高程序的执行效率。

case:

public class FutureThreadPoolDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //3个任务,目前只有一个线程main来处理,耗时多少?
        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        long startTime = System.currentTimeMillis();
        FutureTask<String> task1 =  new FutureTask<String>(()->{
           try{ TimeUnit.MILLISECONDS.sleep(500);}catch(InterruptedException e) {e.printStackTrace();}
           return "task1 over";
        });
        threadPool.submit(task1);
        FutureTask<String> task2 =  new FutureTask<String>(()->{
            try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();}
            return "task2 over";
        });
        threadPool.submit(task2);
        System.out.println(task1.get());
        System.out.println(task2.get());
        try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();}
        threadPool.shutdown(); //关闭线程池
        long endTime = System.currentTimeMillis();
        System.out.println("----costTime:"+(endTime-startTime)+"毫秒");
        System.out.println(Thread.currentThread().getName()+"\t-------end");
    }
//    private static void m1() {
//        //3个任务,目前只有一个线程main来处理,耗时多少?
//        long startTime = System.currentTimeMillis();
//        try{ TimeUnit.MILLISECONDS.sleep(500);}catch(InterruptedException e) {e.printStackTrace();}
//        try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();}
//        try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();}
//        long endTime = System.currentTimeMillis();
//        System.out.println("----costTime:"+(endTime-startTime)+"毫秒");
//        System.out.println(Thread.currentThread().getName()+"\t-------end");
//    }
}

缺点

  1. get()方法容易引起阻塞,如果没有计算完成,容易导致程序阻塞。如下程序:
/**
 * @author ygf
 * @date 2022/9/18 15:31
 * 1.get容易导致阻塞,一般建议放到程序后面,一旦调用不见不散,非要等到结果才会离开,不管计算是否完成,容易引起阻塞。
 * 2.假如我不愿意等待很长时间,我希望可以过时不候,到时间了可以自动离开用:task1.get(3,TimeUnit.SECONDS)
 */
public class FutureAPIDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        FutureTask<String> task1 =  new FutureTask<String>(()->{
            try{ TimeUnit.MILLISECONDS.sleep(5000);}catch(InterruptedException e) {e.printStackTrace();}
            return "task1 over";
        });
        Thread t1 =  new Thread(task1,"t1");
        t1.start();
//        System.out.println(task1.get()); //调用get(),就会阻塞,不见不散,非要等到结果才会离开
        System.out.println(task1.get(3,TimeUnit.SECONDS));
        System.out.println(Thread.currentThread().getName()+"----忙其他任务了");
    }
}
  1. isDone()轮询 容易引起cpu空转,耗费更多的资源
public class FutureAPIDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        FutureTask<String> task1 =  new FutureTask<String>(()->{
            try{ TimeUnit.MILLISECONDS.sleep(5000);}catch(InterruptedException e) {e.printStackTrace();}
            return "task1 over";
        });
        Thread t1 =  new Thread(task1,"t1");
        t1.start();
//        System.out.println(task1.get()); //调用get(),就会阻塞,不见不散,非要等到结果才会离开
//        System.out.println(task1.get(3,TimeUnit.SECONDS));
        System.out.println(Thread.currentThread().getName()+"----忙其他任务了");
//        System.out.println(task1.get());
        while (true){
            if(task1.isDone()){
                System.out.println(task1.get());
                break;
            }else{
                try{ TimeUnit.MILLISECONDS.sleep(300);}catch(InterruptedException e) {e.printStackTrace();}
                System.out.println("正在处理中.......");
            }
        }
    }
}

返回结果

image.png

总结

Future对于结果的获取不是很友好,这就是CompletableFuture的诞生的理由了。

目录
相关文章
|
1月前
|
消息中间件 缓存 安全
Future与FutureTask源码解析,接口阻塞问题及解决方案
【11月更文挑战第5天】在Java开发中,多线程编程是提高系统并发性能和资源利用率的重要手段。然而,多线程编程也带来了诸如线程安全、死锁、接口阻塞等一系列复杂问题。本文将深度剖析多线程优化技巧、Future与FutureTask的源码、接口阻塞问题及解决方案,并通过具体业务场景和Java代码示例进行实战演示。
47 3
|
2月前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
38 1
|
7月前
|
Java
Java并发编程:理解并使用Future和Callable接口
【2月更文挑战第25天】 在Java中,多线程编程是一个重要的概念,它允许我们同时执行多个任务。然而,有时候我们需要等待一个或多个线程完成,然后才能继续执行其他任务。这就需要使用到Future和Callable接口。本文将深入探讨这两个接口的用法,以及它们如何帮助我们更好地管理多线程。
|
并行计算 Java
【Future&ForkJoin框架原理】
【Future&ForkJoin框架原理】
|
缓存 Java 数据库连接
线程的创建、Lambda函数式接口?Runnable和Callable之间的适配?动态修改线程任务?这里带你图解Java线程池
上面只是提到了对于Thread执行任务的一种动态实现方法,肯定还有其他的。 那么动态实现有什么好处呢? 当我们有很多个任务的时候,我们如果一直使用new,再让gc的话,那么对于系统资源的消耗无疑是巨大的。 那么这个时候,如果我们固定一下,专门拿几个线程来处理并发任务呢?但是当并发任务很多又该怎么办? 这个时候就引入了池化思想 —— Pool 什么是池? 在学JDBC的时候我们知道了连接池,在学Spring的时候,我们又接触到了对象池。 其实按理来说线程池应该是大家在初学JavaSE的时候应该就遇到的,这里我们再来讲一下。 线程池,就是用一个容器来管理线程,这个容器叫做池(Poo
116 0
线程的创建、Lambda函数式接口?Runnable和Callable之间的适配?动态修改线程任务?这里带你图解Java线程池
|
存储 Java
JUC基础(二)—— Future接口 及其实现
JUC基础(二)—— Future接口 及其实现
168 1
创建多线程的方式三:实现Callable接口。
创建多线程的方式三:实现Callable接口。
72 0
创建多线程的方式二:实现Runnable接口
创建多线程的方式二:实现Runnable接口
65 0
|
设计模式 Java API
【JUC基础】15. Future模式
Future 模式是多线程开发中非常常见的一种设计模式,它的核心思想是异步调用。当我们需要调用一个函数方法时,如果这个函数执行得很慢,那么我们就要进行等待。但有时候,我们可能并不急着要结果。因此,我们可以让被调者立即返回,让它在后台慢慢处理这个请求。对于调用者来说,则可以先处理一些其他任务,在真正需要数据的场合再去尝试获得需要的数据。
150 0
【JUC基础】15. Future模式
|
设计模式 Java
多线程设计模式 - Future模式之JAVA原生实现
多线程设计模式 - Future模式之JAVA原生实现
132 0