JUC—Callable接口
一、callable接口是什么?
面试题:
获得多线程的方法几种?
正确答案如下:
传统的 是继承thread类和实现runnable接口,
java5以后又有实现 callable接口 和 java的线程池获得
函数式接口
这是一个函数式接口,因此可以用作lambda表达式或方法引用的赋值对象 。
二、与runnable对比(实现方法对比)
面试题:callable接口与runnable接口的区别? 答:(1)是否有返回值 (2)是否抛异常 (3)落地方法不一样,一个是run,一个是call
创建新类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; } }
三、怎么用?
(1)直接替换runnable是否可行?
不可行,因为:thread类的构造方法根本没有Callable
这像认识一个不认识的同学,我可以找中间人介绍。
中间人是什么? java多态,一个类可以实现多个接口!!
FutureTask<Integer> ft = new FutureTask<Integer>( new MyThread()); new Thread( ft , "AA" ).start();
运行成功后如何获得返回值?
ft .get();
FutureTask
1、FutureTask是什么?
未来的任务,用它就干一件事,异步调用
main方法就像一个冰糖葫芦,一个个方法由main串起来。
但解决不了一个问题:正常调用挂起堵塞问题
例子:
( 1 )老师上着课,口渴了,去买水不合适,讲课线程继续,我可以单起个线程找班长帮忙买水,
水买回来了放桌上,我需要的时候再去 get 。
( 2 ) 4 个同学, A 算 1+20,B 算 21+30,C 算 31* 到 40,D 算 41+50 ,是不是 C 的计算量有点大啊,
FutureTask 单起个线程给 C 计算,我先汇总 ABD ,最后等 C 计算完了再汇总 C ,拿到最终结果
( 3 )高考:会做的先做,不会的放在后面做
2、原理
在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给Future对象在后台完成,
当主线程将来需要时,就可以通过Future对象获得后台作业的计算结果或者执行状态。
一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。
仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成,
就不能再重新开始或取消计算。get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态,
然后会返回结果或者抛出异常。
只计算一次
get方法放到最后
3、代码
package demo1; import java.util.concurrent.*; class MyThread implements Runnable{ @Override public void run() { System.out.println("继承runnable方法"); } } class MyThread2 implements Callable<Integer>{ @Override public Integer call() throws Exception{ System.out.println(Thread.currentThread().getName()+"come in callable"); return 200; } } public class Callablelearn { public static void main(String[] args) throws Exception{ /** * 建立futureTask (创建中间人) 介绍线程与callable认识, * */ // FutureTask<Integer> futureTask = new FutureTask(new MyThread2()); FutureTask<Integer> futureTask = new FutureTask<>(()->{ System.out.println(Thread.currentThread().getName()+"come in callable"); return 1024; }); FutureTask<Integer> futureTask2 = new FutureTask<>(()->{ System.out.println(Thread.currentThread().getName()+"come in callable"); return 2048; }); new Thread(futureTask,"zhangsan").start(); new Thread(futureTask2,"lisi").start(); while(!futureTask.isDone()){ System.out.println("------wait"); } System.out.println(futureTask.get()); System.out.println(Thread.currentThread().getName()+"come over"); } /** * 在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给Future对象在后台完成, * 当主线程将来需要时,就可以通过Future对象获得后台作业的计算结果或者执行状态。 * * 一般FutureTask多用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。 * * 仅在计算完成时才能检索结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成, * 就不能再重新开始或取消计算。get方法而获取结果只有在计算完成时获取,否则会一直阻塞直到任务转入完成状态, * 然后会返回结果或者抛出异常。 * * 只计算一次 * get方法放到最后 */ }