📜  Java中的Future和FutureTask(1)

📅  最后修改于: 2023-12-03 15:31:57.046000             🧑  作者: Mango

Java中的Future和FutureTask

在Java多线程编程中,我们可能需要在一个线程中进行一些异步操作,这时候我们就需要使用Future和FutureTask。

Future

首先来介绍一下Future。Future表示异步计算的结果,它提供了一些方法来检查计算是否完成以及获取计算结果。

方法
  • boolean isDone():返回true,当且仅当计算完成时。
  • boolean isCancelled():返回true,当且仅当任务被取消时。
  • boolean cancel(boolean mayInterruptIfRunning):试图取消正在执行的任务。如果任务已经完成或者已经被取消,那么这个方法将返回false。否则,它将启动取消任务的执行。
  • V get():等待计算完成,然后返回其结果。
  • V get(long timeout, TimeUnitunit):等待计算完成,最多等待指定的时间。
举例说明
public class FutureExample {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(5);

        Future<Integer> future = executor.submit(() -> {
            Thread.sleep(1000);
            return 123;
        });

        while (!future.isDone()) {
            System.out.println("Calculating...");
            Thread.sleep(300);
        }

        System.out.println("Result: " + future.get());

        executor.shutdown();
    }
}

在这个例子中,我们使用ExecutorService创建了线程池,并使用submit提交了一个任务。这个任务会睡眠1秒,然后返回整数123。我们在主线程中调用future.isDone()来检查计算是否完成,如果还没有完成,就输出"Calculating..."并睡眠300毫秒。当计算完成后,我们就可以通过future.get()获取计算结果。

FutureTask

FutureTask实现了Future接口,同时它也是Runnable的子类,因此它既可以作为一个异步任务的返回结果使用,也可以在Executor中执行。和Future不同的是,FutureTask可以通过构造函数或者set方法设置计算结果,因此可以用于那些预先知道结果的计算,可以减少不必要的线程等待时间。

构造函数

我们可以使用以下构造函数来创建FutureTask:

  • FutureTask(Callable callable):callable是一个返回值类型为V的函数,我们将它包装为FutureTask。
  • FutureTask(Runnable runnable, V result):我们可以传递一些计算出来的结果,可以在所有线程开始执行任务之前就知道结果,并进行缓存操作。
方法

FutureTask继承了重载的get()方法,可以通过get()方法同步等待任务完成并返回执行结果,也可以通过get(long timeout, TimeUnit unit)方法来指定等待任务的最长时间。

public class FutureTaskExample {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(5);

        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            Thread.sleep(1000);
            return 123;
        });

        executor.submit(futureTask);

        while (!futureTask.isDone()) {
            System.out.println("Calculating...");
            Thread.sleep(300);
        }

        System.out.println("Result: " + futureTask.get());

        executor.shutdown();
    }
}

在这个例子中,我们使用ExecutorService创建了线程池,然后创建了一个FutureTask。其中,我们传入一个Callable对象来实现异步计算。我们使用submit()方法将FutureTask提交给线程池,最终在主线程中调用futureTask.get()获取计算结果。

总结

在多线程编程中,当我们需要进行异步计算、并发编程的时候,Future和FutureTask是非常有用的工具。我们可以使用它们来检查任务是否完成,获取计算结果,甚至可以指定等待的最长时间。同时,FutureTask还具有Runnable的特性,可以在线程中执行计算任务,非常灵活和实用。