혈액 배경 교훈 : 재고 데이터 마이그레이션의 스레드 풀을 사용하지만, 마이그레이션이 실패 할 데이터의 수, 예외 로그 인쇄는 항상있다
살인의 원인
나는 들었 parallelStream
매일 개발하기 때문에 병렬 흐름이, 좋은 일이 stream
많은 장면 직렬 스트림, 바로 적용 할 수있는 마이그레이션 프로그램을 작성할 필요, 즉 * 그 다음 지금 설치하지 마십시오 신속하게 설치하게하지, 경우 . 또한 재치 알고 , 일반적인 포크의 사용 / 이러한 기능을 수행하기 위해 풀에 참가, 풀은 기본적으로 모든 병렬 스트림에 의해 공유되는, 포크 / 수영장 각 프로세서에 대해 스레드를 할당합니다 조인 JVM 배경에 , 대응을 해결 방법으로 자신의 스레드 풀을 만드는 것입니다
ForkJoinPool pool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
pool.submit(() -> {
list.parallelStream().collect(Collectors.toList());
});
复制代码
그래서 여기에서 심어 지뢰.
제출하거나 실행
public static void main(String[] args) throws InterruptedException, ExecutionException {
final ExecutorService pool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
List<Integer> list = Lists.newArrayList(1, 2, 3, null);
//1.使用submit
pool.submit(() -> {
list.parallelStream().map(a -> a.toString()).collect(Collectors.toList());
});
TimeUnit.SECONDS.sleep(3);
//2.使用 execute
pool.execute(() -> {
list.parallelStream().map(a -> a.toString()).collect(Collectors.toList());
});
//3.使用submit,调用get()
pool.submit(() -> {
list.parallelStream().map(a -> a.toString()).collect(Collectors.toList());
}).get();
TimeUnit.SECONDS.sleep(3);
}
复制代码
위의 사용 사례에서 실행하는 독자는, 별도의 찾을 submit
방법 및 오류 로그를 인쇄 사용하지 않습니다 execute
오류 로그를 인쇄하는 방법을하지만, 할 submit
받는 돌아 FutureJoinTask
호출 get()
예외가 발생합니다 방법. 따라서 진실 더티 데이터의 일부 배치에 존재하는 데이터가 널 값, 널 값은 예외가 발생 될 때 통과하는 것이 아니라 예외 로그에 submit
실시간 처리를 잡을 아닌 (상처)를 인쇄한다 캐치되지 않는 예외는 반환 된 클래스 결과에 포장되어 FutureJoinTask
, 다시 포기하지 않았다.
비동기 결과를 반환하지 않는 경우, 사용하지 마십시오 submit
방법을
결론은 첫째, 나는 평범한 생각, 실수를 submit
하고 execute
의 차이는 단지 비동기 결과에 반환하고, 단계가 결과를 반환하지 않지만, 사실은 잔인. 에서 submit()
논리는 비동기 작업을 던져 예외를 catch하는 것 포함해야하지만, 부적절한 사용하기 때문에 예외가 다시 발생하지 않는 원인이되었다.
이제 질문을 물어 ForkJoinPool#submit()
답례로 ForkJoinTask
, 비동기 작업의 결과를 얻을 수 있습니다를 지금 비동기 예외가 발생, 우리는 어떻게 될 작업의 결과를 얻으려고? 우리는 직접 볼 ForkJoinTask#get()
소스.
public final V get() throws InterruptedException, ExecutionException {
int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
doJoin() : externalInterruptibleAwaitDone();
Throwable ex;
if ((s &= DONE_MASK) == CANCELLED)
throw new CancellationException();
//这里可以直接看到,异步任务出现异常会在调用get()获取结果的时候,会被包装成ExecutionException再次抛出
if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
throw new ExecutionException(ex);
return getRawResult();
}
复制代码
GET () 결과를 얻기를 호출 할 때 비동기 작업에 이상이 될 것으로 포장됩니다 ExecutionException
다시 발생하지만, 예외가 포착되는 경우는? 모든 스레드 스레드가 다시 작성해야하는, 동일하게 유지 Thread#run()
, 방법을 게시 ForkJoinPool
로 포장됩니다 스레드 ForkJoinWorkerThread
, 그래서 우리는보고 ForkJoinWorkerThread#run()
구현입니다.
public void run() {
if (workQueue.array == null) { // only run once
Throwable exception = null;
try {
onStart();
pool.runWorker(workQueue);
} catch (Throwable ex) {
//出现异常,捕获,再次抛出会在调用ForkJoinTask#get()的时候
exception = ex;
} finally {
try {
onTermination(exception);
} catch (Throwable ex) {
if (exception == null)
exception = ex;
} finally {
pool.deregisterWorker(this, exception);
}
}
}
}
复制代码
위의 분석을 기반으로 ForkJoinPool
, 스레드 풀의 전부는 아닙니다 submit
및 execute
실현과 같이, 우리는 종종 스레드 풀을 사용하는 ThreadPoolThread
것입니다 무엇을 달성하기 위해, 같은 생각, 우리는 필요 에 전달 찾을 ThreadPoolThread
궁극적으로 포장됩니다 비동기 작업 이는 Thread
서브 클래스 나 구현 java.lang.Runnable#run
, 대답은java.util.concurrent.FutureTask
public void run() {
...
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
//捕获异常
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
}
....
}
复制代码
개요
java.util.concurrent.ExecutorService#submit(java.lang.Runnable)
이러한 스레드 풀 설정, 사실, 우리의 생각은하지만,에 스레드 풀에가 제한되어서는 안되는 이유 는 비정상적인 결과가 비동기인지, 비동기 작업 결과를 획득 , FutureTask
JDK 등의 동시성 도구를 제공 우리는 아주 좋은 대답이 부여 된 실행 비동기 작업이 발생 나타나면 또한 비동기 비정상적인 결과에 속하는 결과 비동기 작업을 얻을를, 이상은, 결과를 얻는 작업은 예외가 재 포장한다
저자 : PLZ 빨간색 스카프 나에게 전화
출처 : juejin.im/post/5d15c4 ...
그렇지 않으면 법적 책임을 추구 할 수있는 권리를이 블로그를 다시 인쇄하지만,이 섹션에 의해 선언 된 저자의 동의가 유지되어야하지 않고, 및 기사 페이지의 명백한 위치에 원래 연결을 제공에 오신 것을 환영합니다. 코드 워드가 쉽지 않다, 내 글의 요점을 찬양하는 가장 큰 힘이다