在《Java 自定义线程池的线程工厂》一文中介绍了如何优雅地自定义线程工厂,本文介绍如何自定义线程池的任务,并拿到返回值。
首先自定义一个任务类,实现Callable接口,重写call函数,定义其返回类型为Integer。
import java.util.concurrent.Callable;
public class CalcTask implements Callable<Integer> {
private int num;
public CalcTask(int num) {
this.num = num;
}
@Override
public Integer call() throws Exception {
doSth();
// 定义求和变量
return sum(num);
}
private Integer sum(Integer num) {
// 定义求和变量
int result = 0;
for (int i = 1; i <= num; i++) {
result += i;
}
return result;
}
private void doSth() {
System.out.println("do something");
}
}
创建任务类的优势是在自定义请求报文和返回报文同时,可以处理超级复杂的业务逻辑,解决在线程池主体函数所在类中代码量非常多的问题。下面构建线程池主体函数,用于分别计算1-100和1-200的值:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class ThreadPoolTest {
/**
* 线程池创建提交任务——java
* 用线程池分别计算1-100和1-200的值
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// 创建线程池对象并指定线程数量
ExecutorService tp = Executors.newFixedThreadPool(2);
List<Integer> results = new ArrayList<>();
// 创建任务实现对象
FutureTask<Integer> futureTask100 = new FutureTask<>(new CalcTask(100));
FutureTask<Integer> futureTask200 = new FutureTask<>(new CalcTask(200));
// 使用submit开启两个任务
Future<Integer> f1 = (Future<Integer>) tp.submit(futureTask100);// 5050
Future<Integer> f2 = (Future<Integer>) tp.submit(futureTask200); // 20100
results.add(f1.get());
System.out.println("任务返回值依次拿回,阻塞中。。。");
results.add(f2.get());
System.out.println(results);
// 销毁线程池
tp.shutdown();
}
}
这里通过get方法获取执行结果,但该方法会阻塞直到任务返回结果。