Callable实现类介绍和函数式接口介绍

1:Callable实现类介绍

首先我们都知道,在Java中最常见的是继承Thread类和实现Runnable接口来实现多线程(

这里我推荐采用实现接口的方式来实现多线程,原因有两点:

1、Java的设计是单继承的设计,如果采用继承Thread的方式实现多线程则不能继承其他的类

2、采用接口能够更好的实现数据共享。线程的启动需要Thread类的start方法,如果采用继承的方式每次新建一个线程时,每个新建线程的数据都会单独的存在线程内存中,这样每个线程会单独的操作自己线程的数据,不能更好的实现线程之间的数据共享)

但是无论以上哪种方式实现多线程,都存在一个问题,就是线程run方法没有返回值,如果一个线程需要有返回值时,可以采用本章讲的实现Callable接口来实现多线程

首先看一下Callable接口的源码

 1 @FunctionalInterface
 2 public interface Callable<V> {
 3     /**
 4      * Computes a result, or throws an exception if unable to do so.
 5      *
 6      * @return computed result
 7      * @throws Exception if unable to compute a result
 8      */
 9     V call() throws Exception;
10 }

首先明确一点这是一个函数式接口,其中的@FunctionalInterface定义了这个接口为函数式接口(具体函数式接口和普通接口有何区别可以自行查阅相关资料) ,Callable接口接受一个泛型作为接口中call方法的返回值类型,因此我们在使用时需要传入一个返回值类型。

然后我去实现这个接口来定义我自己的线程类,这里我传入了一个String类型作为接口call方法的返回值类型,然后实现了call方法,将result作为返回结果返回

 1 public class MyCallable<String> implements Callable<String> {
 2  
 3     private int tickt=10;
 4     
 5     @Override
 6     public String call() throws Exception {
 7         // TODO Auto-generated method stub
 8         String result;
 9         while(tickt>0) {
10             System.out.println("票还剩余:"+tickt);
11             tickt--;
12         }
13         result=(String) "票已卖光";
14         return result;
15     }
16  
17 }

下面就看一下怎样启动采用实现Callable接口的线程

 1 package Multi_Thread;
 2 import org.apache.commons.io.FileUtils;
 3 
 4 import java.io.File;
 5 import java.io.IOException;
 6 import java.net.URL;
 7 import java.util.concurrent.*;
 8 
 9 /**
10  * 实现callable接口
11  */
12 public class CallMethod implements Callable<Boolean> {
13     String url;
14     String name;
15 
16     public CallMethod(String url, String name) {
17         this.url = url;
18         this.name = name;
19     }
20 
21     @Override
22     public Boolean call() {
23         WebDownloader down = new WebDownloader();
24         try {
25             down.downloader(url,name);
26         } catch (IOException e) {
27             e.printStackTrace();
28         }
29         return null;
30     }
31     class WebDownloader
32     {
33         public void downloader(String url,String name) throws IOException {
34             FileUtils.copyURLToFile(new URL(url),new File(name));
35         }
36     }
37 
38     public static void main(String[] args) throws ExecutionException, InterruptedException {
39         CallMethod callMethod = new CallMethod("https://csdnimg.cn/medal/github@240.png","a.png");
40         //创建执行服务
41         ExecutorService executorService = Executors.newFixedThreadPool(1);
42         //提交执行
43         Future<Boolean> submit = executorService.submit(callMethod);
44         //获取jieguo
45         Boolean aBoolean = submit.get();
46         System.out.println(aBoolean);
47         executorService.shutdown();
48 
49     }
50 }

2:函数式接口

1. 函数式接口是个啥?

它是一个接口,在这个接口里面只能有一个抽象方法(但可以包含多个默认方法、静态方法、继承自Object的公有方法)。主要用于方法引用以及结合Lambda表达式使用。

2. 怎么定义?

@FunctionalInterface

public Interface MyFunction {
  public void do();
  //也可以包含如下方法
  //默认方法
  default void ddo() {
    //do what you want
  }
  //静态方法
  public static void sdo() {
    //do what you want
  }
  //继承自Object的公有方法
  @Override
  public boolean equals(Object obj);
}
3. 怎么用?
public void main(String[] args) {
  MyFunction mf = ()-> System.out.println("我是do方法");//l这个lambda表达式相当于实现了接口中的抽象方法,
  mf.do();
}
输出:
我是do方法

注意:JDK7及其以下版本JDK只能包含公开且抽象的方法(默认由public abstract修饰),而JDK8开始可以包含default、static修饰的非抽象方法。

原文地址:https://www.cnblogs.com/henuliulei/p/13949889.html