runnable、callable、consumer、supplier

Java 没有委托的概念; 相反,如果需要一个指向函数的指针,可以创建内联匿名类(或 Java 8 的 lambda 表达式),它们是为此建议设计的某些接口的实现(也称为 Java 8 的功能接口)。 然而,随着 Java 的发展,越来越多的此类接口被添加进来。 虽然它们看起来非常相似且令人困惑,但它们中的每一个都有一个独特的特征,使其与众不同。 可以将它们中的许多映射到 .NET 中的相同类型。 下表列出了一些著名的接口,但还有更多。 例如,为了支持带有两个参数的函数,Java 有另一个接口称为 BiFunction,如果您需要更多参数,则必须创建自己的接口。 请记住,如果唯一的区别是类型参数的数量,Java(最高版本 10)不支持相同的类名。 (在 .NET 中有各种 Func 和 Action 类型,最多有 16 个类型参数。)
在这里插入图片描述
Supplier () -> x
Consumer x -> ()
Callable () -> x throws ex
Runnable () -> ()
Function x -> y


Runnable


Since Java’s early days, multithreading has been a major aspect of the
language. Runnable is the core interface provided for representing
multithreaded tasks, and Java 1.5 provided Callable as an improved
version of Runnable.

Runnable 接口是一个函数式接口,有一个不接受任何参数或返回任何值的 run() 方法。
这适用于我们不寻找线程执行结果的情况,例如传入事件日志记录:

public interface Runnable {
    public void run();
}
public class EventLoggingTask implements  Runnable{
    private Logger logger
      = LoggerFactory.getLogger(EventLoggingTask.class);

    @Override
    public void run() {
        logger.info("Message");
    }
}

在此示例中,线程将仅从队列中读取消息并将其记录在日志文件中。任务没有返回任何值。 我们可以使用 ExecutorService 启动任务:

public void executeTask() {
    executorService = Executors.newSingleThreadExecutor();
    Future future = executorService.submit(new EventLoggingTask());
    executorService.shutdown();
}

Callable


Callable 接口是一个通用接口,包含一个返回通用值 V 的 call() 方法:

public interface Callable<V> {
    V call() throws Exception;
}
public class FactorialTask implements Callable<Integer> {
    int number;

    // standard constructors

    public Integer call() throws InvalidParamaterException {
        int fact = 1;
        // ...
        for(int count = number; count > 1; count--) {
            fact = fact * count;
        }

        return fact;
    }
}
@Test
public void whenTaskSubmitted_ThenFutureResultObtained(){
    FactorialTask task = new FactorialTask(5);
    Future<Integer> future = executorService.submit(task);
 
    assertEquals(120, future.get().intValue());
}

Consumer


从字面意思上我们就可以看得出,consumer接口就是一个消费型的接口,通过传入参数,然后输出值
我们下面就先看一个例子

@Test
public void test_Consumer() {
    //① 使用consumer接口实现方法
    Consumer<String> consumer = new Consumer<String>() {

        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };
    Stream<String> stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
    stream.forEach(consumer);

    System.out.println("********************");

    //② 使用lambda表达式,forEach方法需要的就是一个Consumer接口
    stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
    Consumer<String> consumer1 = (s) -> System.out.println(s);//lambda表达式返回的就是一个Consumer接口
    stream.forEach(consumer1);
    //更直接的方式
    //stream.forEach((s) -> System.out.println(s));
    System.out.println("********************");

    //③ 使用方法引用,方法引用也是一个consumer
    stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
    Consumer consumer2 = System.out::println;
    stream.forEach(consumer);
    //更直接的方式
    //stream.forEach(System.out::println);
}

lambda 表达式作为 consumer

Consumer<String> consumer1 = (s) -> System.out.println(s);

方法引用作为 consumer

Consumer consumer2 = System.out::println;

Supplier


Supplier 接口是一个供给型的接口,其实,说白了就是一个容器,可以用来存储数据,然后可以供其他方法使用的这么一个接口。

@Test
public void test_Supplier() {
    //① 使用Supplier接口实现方法,只有一个get方法,无参数,返回一个值
    Supplier<Integer> supplier = new Supplier<Integer>() {
        @Override
        public Integer get() {
            //返回一个随机值
            return new Random().nextInt();
        }
    };

    System.out.println(supplier.get());

    System.out.println("********************");

    //② 使用lambda表达式,
    supplier = () -> new Random().nextInt();
    System.out.println(supplier.get());
    System.out.println("********************");

    //③ 使用方法引用
    Supplier<Double> supplier2 = Math::random;
    System.out.println(supplier2.get());
}

看一下这段代码,我们通过创建一个 Supplier 对象,实现了一个 get 方法,这个方法无参数,返回一个值;所以,每次使用这个接口的时候都会返回一个值,并且保存在这个接口中,所以说是一个容器。

Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                //返回一个随机值
                return new Random().nextInt();
            }
        };
Supplier<Double> supplier2 = Math::random;
System.out.println(supplier2.get());
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会说话的皮卡丘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值