使用 Lambdas 定义内联异步任务
虽然良好的软件设计通常可以最大限度地提高代码的可重用性,但有时通过 Lambda 表达式在代码中内联定义异步任务以最大化代码可读性会很有用。
在这个例子中,我们将创建一个包含 main()
方法的类。在此方法中,我们将使用 Lambda 表达式来创建和执行 Callable 和 Runnable <T>的实例。
AsyncExample3.java
import lombok.extern.java.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
@Log
public class AsyncExample3 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<Integer>> futures = new ArrayList<>();
for(int i = 0; i < 5; i++){
final int index = i;
executorService.execute(() -> {
int timeout = getTimeout();
log.info(String.format("Runnable %d has been submitted and will sleep for %d seconds", index, timeout));
try {
TimeUnit.SECONDS.sleep(timeout);
} catch (InterruptedException e) {
log.warning(e.getMessage());
}
log.info(String.format("Runnable %d has finished sleeping", index));
});
Future<Integer> submittedFuture = executorService.submit(() -> {
int timeout = getTimeout();
log.info(String.format("Callable %d will begin sleeping", index));
try {
TimeUnit.SECONDS.sleep(timeout);
} catch (InterruptedException e) {
log.warning(e.getMessage());
}
log.info(String.format("Callable %d is done sleeping", index));
return timeout;
});
futures.add(submittedFuture);
}
executorService.shutdown();
while(!futures.isEmpty()){
for(int j = 0; j < futures.size(); j++){
Future<Integer> f = futures.get(j);
if(f.isDone()){
try {
int timeout = f.get();
log.info(String.format("A task just completed after sleeping for %d seconds", timeout));
futures.remove(f);
} catch (InterruptedException | ExecutionException e) {
log.warning(e.getMessage());
}
}
}
}
}
public static int getTimeout(){
return ThreadLocalRandom.current().nextInt(1, 20);
}
}
注意事项:
在上面的输出中有几点需要注意,
- Lambda 表达式可以访问定义它们的作用域可用的变量和方法,但所有变量必须是最终的(或有效的最终)才能在 lambda 表达式中使用。
- 我们不必明确指定我们的 Lambda 表达式是 Callable 还是 Runnable <T>,返回类型由返回类型自动推断。