本文,我们将介绍带参数的 Java 8 Runnable 和 Callable 表达式。Java 8 的两个接口 Runnable 和 Callable 都添加了 @FunctionalInterface 注解。因此,我们可以直接使用 Lambda 表达式来实现 run() 和 call() 方法。当然了,本文,我们关注的是如何将参数传递给 Runnable 和 Callable。
带参数的 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 style = (Book b) -> System.out.println("Book Id:"+b.getId() + ", Book Name:"+b.getName());
list.forEach(style);
};
如果要将一个参数传递给 run() 方法,需要使用 final 修饰符,用于声明传递的变量是不可变更的。
final List list = Arrays.asList(new Book(1, "Ramayan"), new Book(2, "Mahabharat"));
Runnable r = () -> {
Consumer 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 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 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 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 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 接口早在 Java 5 中就已经引入了,这是一个范型接口,V 用于表示返回值的类型。而 Java 8 则给 Callable 接口添加了 @FunctionalInterface 注解。使得可以使用 Lambda 表达式来创建一个 Callable 实例。
Callable callableObj = () -> { return 2*3; };
是不是和 Runnable 的差不多,其实 Runnable 和 Callable 两者最大的区别是,前者的 run() 方法没有返回值,而后者的 call() 方法可以有返回值。
上面这句代码,等同于不使用 Lambda 表达式的以下代码
Callable callableObj = new Callable() {
@Override
public Integer call() throws Exception {
return 2*3;
}
};
跟 Runnable 一样,如果要在 Lambda 中使用一个外部的参数,则必须给该参数添加 final 修饰符。若下所示
final int val = 10;
Callable 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 integers = Arrays.asList(1,2,3,4,5);
Callable callableObj = () -> {
int result = integers.stream().mapToInt(i -> i.intValue()).sum();
return result;
};
ExecutorService service = Executors.newSingleThreadExecutor();
Future 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