병렬 흐름parallel,CompletableFuture와Executors 스레드 풀의 사용과 차이
1. 리스트를 직접 만듭니다.
// list ,Collections.synchronizedList ,CopyOnWriteArrayList
List list = Arrays.asList(new String[10000]);
2. parallel 병렬 스트리밍 사용:
list.stream().parallel().forEach(a -> {
// .....
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
병렬 흐름 특징:
, , , ;
list CPU , ;
3. Completable Future 사용
3.1 사용자 정의 스레드 풀을 사용하지 않음:
// supplyAsync ,runAsync
list.stream().map(a -> CompletableFuture.supplyAsync(() -> {
// .....
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return a;
})).collect(Collectors.toList()).stream().map(CompletableFuture::join).collect(Collectors.toList());
주요 내용:
, 。
3.2 사용자 정의 스레드 풀 사용:
ExecutorService executor = Executors.newFixedThreadPool(Math.min(list.size(), 100));
list.stream().map(a -> CompletableFuture.supplyAsync(() -> {
// .....
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return a;
}, executor)).collect(Collectors.toList()).stream().map(CompletableFuture::join).collect(Collectors.toList());
보충:
1. 스레드 수량의 계산 공식:
T( ) = N( ) * u( cpu ) * (1 + E( )/C( ));
2. 서버 코어 수를 가져옵니다.
int count = Runtime.getRuntime().availableProcessors();
3. 중점을 두다.
여기join방법은CompletableFuture의get()방법과 유사합니다. 모두 라인을 막고 결과를 기다리지만join방법은 이상을 던지지 않습니다. 이상을 처리할 필요가 없습니다. 코드를 더욱 편리하게 하고 get방법은 이상을 던집니다.
4. Executors 사용(스레드 풀은 여러 개 있음)
list.forEach(a ->
executor.submit(() -> {
// .....
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
})
);
executor.shutdown();
while (true) {
if (executor.isTerminated()) {
System.out.println(" !!!");
break;
}
Thread.sleep(10);
}
5. 요약:
idea , :
runAsync: ;
supplyAsync: ;
thenApply: future , ;
thenApplyAsync: ;
thenCompose: futrue
thenCombine: future, , future