简介
这只是我在实际中的写法简版。记录一下。
首先定义ThreadHelper 工具类
package com.java.ccs.basicDemo.thread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
import java.util.function.Supplier;
import java.util.stream.Stream;
/**
* @author Caocs
* @date 2020/5/26
*/
public class ThreadHelper {
private static final Logger logger = LoggerFactory.getLogger(ThreadHelper.class);
private static final int IOPOOLSIZE = 50;
public static ThreadPoolExecutor ioPool;
static {
ioPool = new ThreadPoolExecutor(IOPOOLSIZE,
2 * IOPOOLSIZE,
5L,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(2000),
new ThreadPoolExecutor.DiscardOldestPolicy());
ioPool.allowCoreThreadTimeOut(true);
}
private static <T> List<T> getTaskResult(int timeout, Stream<CompletableFuture<T>> taskStream) {
final List<T> result = Collections.synchronizedList(new ArrayList<>());
CompletableFuture[] allPromises = taskStream.map(t ->
t.exceptionally(e -> {
t.cancel(true);
logger.error(e.toString());
return null;
}).thenAccept(result::add))
.toArray(CompletableFuture[]::new);
try {
CompletableFuture.allOf(allPromises).get(timeout, TimeUnit.MILLISECONDS);
for (CompletableFuture allPromise : allPromises) {
allPromise.cancel(true);
}
} catch (ExecutionException e) {
logger.error(e.toString());
} catch (InterruptedException | TimeoutException e) {
logger.warn(e.toString());
}
return result;
}
public static <T> List<T> getTaskResult(int timeout, List<Supplier<T>> suppliers) {
Stream<CompletableFuture<T>> tasks = suppliers.stream()
.map(x -> CompletableFuture.supplyAsync(x, ioPool));
List<T> result = getTaskResult(timeout, tasks);
return result;
}
}
然后,模拟多任务并发
package com.java.ccs.basicDemo.thread;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* @author Caocs
* @date 2020/5/26
* 模拟使用CompletableFuture执行多个任务
*/
public class DemoTest {
public static void main(String[] args) {
DemoTest demoTest = new DemoTest();
List<String> nameList = Arrays.asList("ccs","name");
// 模拟多个任务
List<Supplier<Integer> > supplierList = nameList.stream()
.map(item->demoTest.toSupplier(item))
.collect(Collectors.toList());
// 并发执行多个任务
List<Integer> result = ThreadHelper.getTaskResult(1000,supplierList);
System.out.println(result);
}
/**
* 模拟将普通方法构建成Supplier方法
*/
public Supplier<Integer> toSupplier(@NotNull String name){
return () -> this.getLength("name");
}
/**
* 模拟一个普通方法
*/
public int getLength(@NotNull String name){
return name.length();
}
}
更新方法
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;
/**
* @author Caocs
* @date 2021/8/25
*/
public class ThreadHelper {
/**
* @param supplierList 需要执行的获取结果的SupplierList。这个里面必须不能为null
* @param timeout 设置超时时间
* @param <T> 结果类型
* @return 最终返回的结果(如果异常等情况,可能导致返回的某个数据为null)
* 注意:
* 只有当supplierList.size>0时才使用该方法,否则可能导致数据转换异常的问题
*/
public static <T> List<T> getTaskResult(List<Supplier<T>> supplierList, int timeout) {
int supplierSize = supplierList.size();
// 用来存放最终的结果
final List<T> result = Collections.synchronizedList(new ArrayList<>());
CompletableFuture[] allPromises = new CompletableFuture[supplierSize];
for (int index = 0; index < supplierSize; index++) {
Supplier<T> supplierItem = supplierList.get(index);
CompletableFuture<Void> future = CompletableFuture
.supplyAsync(supplierItem, ThreadPool.getThreadPool())
.exceptionally((ex) -> {
// 记录异常日志
return null;
})
.thenAccept(result::add); // 每个supplier执行完后得到的结果存放
allPromises[index] = future;
}
try {
// 设置执行超时时间,如果超时则丢弃结果
CompletableFuture.allOf(allPromises).get(timeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} catch (TimeoutException e) {
}
return result;
}
}
Flux执行并发任务
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import java.time.Duration;
import java.util.List;
import java.util.function.Supplier;
/**
* @Author Caocs
* @Date 2023/2/16
*/
public class ParallelExecutor {
public static <U> Mono<List<U>> executeParallel(List<Supplier<U>> supplierList, int timeout) {
// 并发执行
long start = System.currentTimeMillis();
return Flux.fromIterable(supplierList)
.parallel(supplierList.size())
.runOn(Schedulers.fromExecutorService(ThreadPool.getServiceThreadPool()))
.flatMap((supplier) -> {
return Mono.fromSupplier(supplier)
.timeout(Duration.ofMillis(timeout))
.onErrorResume((ex) -> {
CLogHelper.error(ex);
return Mono.empty();
});
})
.sequential()
.collectList()
.doOnSuccess((result) -> {
long cost = System.currentTimeMillis() - start;
CLogHelper.info("Parallel-result", "cost:" + cost + ",result:" + JSON.toJSONString(result));
})
.onErrorResume((ex) -> {
CLogHelper.error("executeParallel", ex);
return Mono.empty();
});
}
}