6.Callable&Future 接口

6.1 Callable 接口
目前我们学习了有两种创建线程的方法-一种是通过创建 Thread 类,另一种是
通过使用 Runnable 创建线程。但是,Runnable 缺少的一项功能是,当线程
终止时(即 run()完成时),我们无法使线程返回结果。为了支持此功能,
Java 中提供了 Callable 接口。
== 现在我们学习的是创建线程的第三种方案---Callable 接口 ==
Callable 接口的特点如下(重点)
  1. 为了实现 Runnable,需要实现不返回任何内容的 run()方法,而对于Callable,需要实现在完成时返回结果的 call()方法。
  2. call()方法可以引发异常,而 run()则不能。
  3. 为实现 Callable 而必须重写 call 方法
  4. 不能直接替换 runnable,因为 Thread 类的构造方法根本没有 Callable
创建新类 MyThread 实现 runnable 接口
class MyThread implements Runnable {@
    Override
    public void run() {}
}
新类 MyThread2 实现 callable 接口
class MyThread2 implements Callable < Integer > {@
    Override
    public Integer call() throws Exception {
        return 200;
    }
}
6.2 Future 接口
当 call()方法完成时,结果必须存储在主线程已知的对象中,以便主线程可
以知道该线程返回的结果。为此,可以使用 Future 对象。
将 Future 视为保存结果的对象–它可能暂时不保存结果,但将来会保存(一旦
Callable 返回)。Future 基本上是主线程可以跟踪进度以及其他线程的结果的
一种方式。要实现此接口,必须重写 5 种方法,这里列出了重要的方法,如下:
  • public boolean cancel(boolean mayInterrupt):用于停止任务。
    ==如果尚未启动,它将停止任务。如果已启动,则仅在 mayInterrupt 为 true
    时才会中断任务。==
  • public Object get()抛出 InterruptedException,ExecutionException:用于获取任务的结果。
    ==如果任务完成,它将立即返回结果,否则将等待任务完成,然后返回结果。
    ==
  • public boolean isDone():
    如果任务完成,则返回 true,否则返回 false
    可以看到 Callable 和 Future 做两件事-Callable 与 Runnable 类似,因为它封
    装了要在另一个线程上运行的任务,而 Future 用于存储从另一个线程获得的结
    果。实际上,future 也可以与 Runnable 一起使用。
    要创建线程,需要 Runnable。为了获得结果,需要 future。
6.3 FutureTask
Java 库具有具体的 FutureTask 类型,该类型实现 Runnable 和 Future,并方
便地将两种功能组合在一起。 可以通过为其构造函数提供 Callable 来创建
FutureTask。然后,将 FutureTask 对象提供给 Thread 的构造函数以创建
Thread 对象。因此,间接地使用 Callable 创建线程。
核心原理:(重点)
在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些
作业交给 Future 对象在后台完成
  • 当主线程将来需要时,就可以通过 Future 对象获得后台作业的计算结果或者执 行状
  • 一般 FutureTask 多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
  • 仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法
  • 一旦计算完成,就不能再重新开始或取消计算
  • get 方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完
    成状态,然后会返回结果或者抛出异常
  • get 只计算一次,因此 get 方法放到最后
demo 案例
6.4 使用 Callable 和 Future
CallableDemo 案例
/**
 * CallableDemo 案列
 */
public class CallableDemo {
    /**
     * 实现 runnable 接口
     */
    static class MyThread1 implements Runnable {
        /**
         * run 方法
         */
        @
        Override
        public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + "线程进入了 run
                        方法 ");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            /**
             * 实现 callable 接口
             */
        static class MyThread2 implements Callable {
            /**
             * call 方法
             * @return
             * @throws Exception
             */
            @
            Override
            public Long call() throws Exception {
                try {
                    System.out.println(Thread.currentThread().getName() + "线程进入了 call
                        方法, 开始准备睡觉 ");
                        Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "睡醒了");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return System.currentTimeMillis();
                }
            }
            public static void main(String[] args) throws Exception {
                //声明 runable
                Runnable runable = new MyThread1();
                //声明 callable
                Callable callable = new MyThread2();
                //future-callable
                FutureTask < Long > futureTask2 = new FutureTask(callable);
                //线程二
                new Thread(futureTask2, "线程二").start();
                for (int i = 0; i < 10; i++) {
                    Long result1 = futureTask2.get();
                    System.out.println(result1);
                }
                //线程一
                new Thread(runable, "线程一").start();
            }
        }
6.5 小结(重点)
  • 在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给 Future 对象在后台完成, 当主线程将来需要时,就可以通过 Future对象获得后台作业的计算结果或者执行状态
  • 一般 FutureTask 多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果
  • 仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成,就不能再重新开始或取消计算。get 方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,然后会返回结果或者抛出异常。
  • 只计算一次
​​​​​​​
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值