前言
学习一下Future和Callable的使用,模拟是顺序累加一串数字得到和,然后使用Future和Callable重新计算一下,看一下运行时间
一、mainPkg
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class mainPkg {
private Integer splt = 10;
private final Long n = 0L;
//开启两个线程并发执行两个入参相同的方法 查看运算情况
public void say(Long m) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
List<Future<String>> priceFutureList = new ArrayList<>();
ArrayList<Callable> callables = new ArrayList<>();
ArrayList<String> strs = new ArrayList<>();
callables.add(new add(n,m));
callables.add(new add1(n,m));
for (Callable callable : callables) {
priceFutureList.add(executorService.submit(callable));
}
//阻塞至任务全部完成
for (Future<String> f : priceFutureList) {
strs.add(f.get());
}
//结束任务
executorService.shutdown();
System.out.println();
}
class add implements Callable{
Long n;
Long m;
public add(Long n, Long m) {
this.n = n;
this.m = m;
}
//单纯的进行累加
@Override
public String call() throws Exception {
long timeStart = System.currentTimeMillis();
addChild addChild = new addChild(n, m);
Long call = addChild.call();
long timeUseMs = System.currentTimeMillis() - timeStart;
String s = "add: 結果"+call+"--耗時 : "+timeUseMs+" ms";
System.out.println(s);
return s;
}
}
class add1 implements Callable{
Long n;
Long m;
public add1(Long n, Long m) {
this.n = n;
this.m = m;
}
//使用拆分并发的方法进行累加
@Override
public String call() throws Exception {
Long mn = 0L;
long timeStart = System.currentTimeMillis();
//复制的add方法
/*addChild addChild = new addChild(n, m);
Long call = addChild.call();
mn = call;*/
//add1方法
ExecutorService add1ExecutorService = Executors.newFixedThreadPool(splt);
Long start = m / splt.longValue();
ArrayList<Callable> callables = new ArrayList<>();
ArrayList<Future<Long>> futures = new ArrayList<>();
for (Long i = 0L; i < splt; i++) {
callables.add(new addChild(start*i,start*(i+1)));
}
for (Callable callable : callables) {
futures.add(add1ExecutorService.submit(callable));
}
for (Future<Long> future : futures) {
mn+= future.get();
}
add1ExecutorService.shutdown();
long timeUseMs = System.currentTimeMillis() - timeStart;
String s = "ad1: 結果"+mn+"--耗時 : "+timeUseMs+" ms";
System.out.println(s);
return s;
}
}
class addChild implements Callable {
Long n;
Long m;
public addChild(Long n, Long m) {
this.n = n;
this.m = m;
}
@Override
public Long call() throws Exception {
return calculation(n,m);
}
}
private Long calculation(Long n, Long m){
Long sum = 0L;
for (Long i = n; i < m; i++) {
sum += i ;
}
return sum;
}
}
二、mainPkgTest
import org.junit.jupiter.api.Test;
class mainPkgTest {
mainPkg m = new mainPkg();
@Test
void say() {
try {
for (Long i = 0L; i < 5; i++) {
m.say(10000000l);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
总结
注释class mainPkg
的70到83行并放开66到68的注释运行测试获取结果为:
反过来注释class mainPkg
的66到68行并放开70到83的注释运行测试获取结果为:
但是经过多次运行后者时,打印结果总是ad1先打印出,我认为这里应该是乱序才对,但得到的却不是,希望能够得到高人指点,谢谢
(对于结果请教了同事,说是jvm对累加进行过优化,换成io操作或者是实际的查询操作效果会更加明显)