带参数的 Java 8 Runnable 和 Callable 表达式范例

yufei       5 年, 7 月 前       8019

本文,我们将介绍带参数的 Java 8 Runnable 和 Callable 表达式。Java 8 的两个接口 RunnableCallable 都添加了 @FunctionalInterface 注解。因此,我们可以直接使用 Lambda 表达式来实现 run()call() 方法。当然了,本文,我们关注的是如何将参数传递给 RunnableCallable

带参数的 Java 8 Runnable Lambda 示例

Java 8 开始支持 lambda 表达式,而且 Java8 的 Runnable 接口也已经添加了 @FunctionalInterface 注解。这意味这我们可以使用一个 Lambda 表达式来创建一个 Runnable 实例。就像下面的代码所示

Runnable r = () -> System.out.println("Hello World!");
Thread th = new Thread(r);
th.start();

上面三行代码,等同于不使用 Lambda 表达式的下面的代码

Runnable r = new Runnable() {
   @Override
   public void run() {
    System.out.println("Hello World!");
   }
};
Thread th = new Thread(r);
th.start(); 

当然了,Lambda 不只是一行代码,还支持多行,就像普通的方法体一样,可以使用大括号 {} 扩起来,比如下面的代码

Runnable r = () -> {
    Consumer<Book> style = (Book b) -> System.out.println("Book Id:"+b.getId() + ", Book Name:"+b.getName());
    list.forEach(style);
}; 

如果要将一个参数传递给 run() 方法,需要使用 final 修饰符,用于声明传递的变量是不可变更的。

final List<Book> list =  Arrays.asList(new Book(1, "Ramayan"), new Book(2, "Mahabharat"));

Runnable r = () -> {
    Consumer<Book> style = (Book b) -> System.out.println("Book Id:"+b.getId() + ", Book Name:"+b.getName());
    list.forEach(style);
}; 

现在,我们把上面的所有代码合并下,一个完整的带参数的 Java 8 Runnable Lambda 表达式示例就完成了

Java8RunnableDemo.java

package cn.twle.runnable;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import cn.twle.Book;
public class Java8RunnableDemo {
    public static void main(String[] args) {
        final List<Book> list =  Arrays.asList(new Book(1, "Ramayan"), new Book(2, "Mahabharat"));
        Runnable r1 = () -> list.forEach(Book::print);
        Thread th1 = new Thread(r1);
        th1.start();
        Runnable r2 = () -> {
            Consumer<Book> style = (Book b) -> System.out.println("Book Id:"+b.getId() + ", Book Name:"+b.getName());
            list.forEach(style);
        };
        Thread th2 = new Thread(r2);
        th2.start();
    }
} 

Book.java

package cn.twle;
public class Book {
        public int id;
        public String name;
        public Book(int id, String name){
            this.id = id;
            this.name = name;
        }
        public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void print(){
               System.out.println("id:"+id + ", Name:"+name);
        }
}

运行结果如下

id:1, Name:Ramayan
Book Id:1, Book Name:Ramayan
id:2, Name:Mahabharat
Book Id:2, Book Name:Mahabharat

当然了,除了使用 Thread 线程来运行 Runnable 外,还可以使用 ExecutorService 运行 Runnable,如下所示

Java8RunnableDemoExecutor.java

package cn.twle.runnable;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import com.concretepage.Book;
public class Java8RunnableDemoExecutor {
    public static void main(String[] args) {
        final List<Book> list =  Arrays.asList(new Book(1, "Ramayan"), new Book(2, "Mahabharat"));
        ExecutorService service =  Executors.newFixedThreadPool(2);
        Runnable r1 = () -> list.forEach(Book::print);
        service.execute(r1);
        Runnable r2 = () -> {
            Consumer<Book> style = (Book b) -> System.out.println("Book Id:"+b.getId() + ", Book Name:"+b.getName());
            list.forEach(style);
        };
        service.execute(r2);
    }
} 

输出结果如下

id:1, Name:Ramayan
id:2, Name:Mahabharat
Book Id:1, Book Name:Ramayan
Book Id:2, Book Name:Mahabharat

是不是和刚刚的输出一样。Thread 和 ExecutorService 本来就是 Java 多线程的两种执行方式。

带参数的 Java 8 Callable Lambda 示例

Callable<V> 接口早在 Java 5 中就已经引入了,这是一个范型接口,V 用于表示返回值的类型。而 Java 8 则给 Callable 接口添加了 @FunctionalInterface 注解。使得可以使用 Lambda 表达式来创建一个 Callable 实例。

Callable<Integer> callableObj = () -> { return 2*3; };

是不是和 Runnable 的差不多,其实 RunnableCallable 两者最大的区别是,前者的 run() 方法没有返回值,而后者的 call() 方法可以有返回值。

上面这句代码,等同于不使用 Lambda 表达式的以下代码

Callable<Integer> callableObj = new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        return 2*3;
    }
};

Runnable 一样,如果要在 Lambda 中使用一个外部的参数,则必须给该参数添加 final 修饰符。若下所示

final int val = 10; 
Callable<Integer> callableObj = () -> { return 2*val; };

Callable 的执行方式也有两种,一种是使用 Thread 类,另一种是使用 ExecutorService 。 Thread 类我们就不多介绍了,这里直接给出如何使用 ExecutorService 的代码

Java8CallableDemo.java

package cn.twle.callable;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Java8CallableDemo {
    public static void main(String[] args) {
        final List<Integer> integers =  Arrays.asList(1,2,3,4,5);
        Callable<Integer> callableObj = () -> {
            int result = integers.stream().mapToInt(i -> i.intValue()).sum();
            return result;
        };
        ExecutorService service =  Executors.newSingleThreadExecutor();
        Future<Integer> future = service.submit(callableObj);
        Integer result=0;
        try {
            result = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("Sum = "+result);
    }
}

输出结果为

Sum = 15
目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.