很多东西不是你觉得有用才去学,而是你学了才知道有用!

1. FutureTask的类图

image.png
public Thread(Runnable target)
public FutureTask(Callable callable)
public FutureTask(Runnable runnable, V result)

Thread 代表的是线程,用来执行任务。
Runable代表的是一个任务。
Callable也代表的是一个任务。
Future 代表的是结果(简单可以这样理解)。

2. Future

  1. package java.util.concurrent;
  2. public interface Future<V> {
  3. boolean cancel(boolean mayInterruptIfRunning);
  4. boolean isCancelled();
  5. boolean isDone();
  6. V get() throws InterruptedException, ExecutionException;
  7. V get(long timeout, TimeUnit unit)
  8. throws InterruptedException, ExecutionException, TimeoutException;
  9. }

3. FutureTask使用Demo

  1. import java.util.concurrent.Callable;
  2. import java.util.concurrent.ExecutionException;
  3. import java.util.concurrent.FutureTask;
  4. import java.util.concurrent.TimeUnit;
  5. public class FutureTaskDemo {
  6. public static void main(String[] args) {
  7. ACallAble aCallAble = new ACallAble();
  8. FutureTask futureTask = new FutureTask(aCallAble);
  9. Thread thread = new Thread(futureTask);
  10. thread.start();
  11. do {
  12. } while (!futureTask.isDone());
  13. //Future更多的暗示你可以在等待这个结果的同时可以使用其他的线程做一些其他的事情
  14. new Thread(() -> {
  15. try {
  16. TimeUnit.SECONDS.sleep(5);
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. }, "其他线程").start();
  21. try {
  22. //获取结果,这里会阻塞等待futureTask执行完成返回结果
  23. //在这个等待的过程可以让其他线程去执行任务
  24. Object result = futureTask.get();
  25. System.out.println("Result:" + result);
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. } catch (ExecutionException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. }
  33. class ACallAble implements Callable {
  34. @Override
  35. public Object call() throws Exception {
  36. Thread.sleep(1000);
  37. return "Thread-Name:" + Thread.currentThread().getName();
  38. }
  39. }

可以看到,使用FutureTask来启动一个线程之后,我们可以监控这个线程是否完成,上面的示例中主线程会一直等待这个新创建的线程直到它返回,其实只要是Future提供的接口,我们在FutureTask中都可以使用,这极大的方便了我们,Future在并发编程中的意义极为重要,Future代表一个未来会发生的东西,它是一种暗示,一种占位符,它示意我们它可能不会立即得到结果,因为它的任务还在运行,但是我们可以得到一个对这个线程的监控对象。

我们可以对线程的执行做一些判断,甚至是控制,比如,如果我们觉得我们等了太久,并且我们觉得没有必要再等待下去的时候,就可以将这个Task取消,还有一点需要提到的是,Future代表它可能正在运行,也可能已经返回,当然Future更多的暗示你可以在等待这个结果的同时可以使用其他的线程做一些其他的事情,当你真的需要这个结果的时候再来获取就可以了,这就是并发,理解这一点非常重要。