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是否可行?

mmnotes://1.png

 

 不可行,因为:thread类的构造方法根本没有Callable

mmnotes://3.png

 

这像认识一个不认识的同学,我可以找中间人介绍。
中间人是什么? java多态,一个类可以实现多个接口!! 

  

mmnotes://0.png 

FutureTask<Integer>  ft  =  new  FutureTask<Integer>( new  MyThread());
new  Thread( ft ,  "AA" ).start(); 

运行成功后如何获得返回值? 

mmnotes://2.png 

ft .get(); 

 

 FutureTask

1、FutureTask是什么?

未来的任务,用它就干一件事,异步调用 

main方法就像一个冰糖葫芦,一个个方法由main串起来。 

但解决不了一个问题:正常调用挂起堵塞问题 

 

   

 mmnotes://1.png 

例子: 

( 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方法放到最后
 */
}

 

posted @ 2019-08-27 21:05  keepsummer  阅读(415)  评论(0编辑  收藏  举报