자바병렬 및 비동기 프로그래밍 자바

병렬 코드,하나 이상의 스레드에서 실행되는 코드는 한 번 많은 경험이 풍부한 개발자의 악몽 이었지만,자바 8 이 성능 향상 트릭을 훨씬 더 관리해야 많은 변화를 가져왔다.

병렬 스트림

자바 8 이전에는 병렬(또는 동시)코드와 순차 코드간에 큰 차이가있었습니다. 비 순차적 코드를 디버깅하는 것도 매우 어려웠습니다. 단순히 중단점을 설정하고 평소처럼 흐름을 통과하면 병렬 측면을 제거 할 수 있습니다.이 측면은 버그의 원인 인 경우 문제입니다.

다행히,자바 8 은 우리에게 스트림을 준,콩 이후 자바 개발자를위한 가장 큰 것은. 이러한 요소들이 무엇인지 모르는 경우,스트림 애피타이저는 기능적 문제의 요소 시퀀스를 처리할 수 있습니다. (여기서 스트림과 링크 간의 비교를 확인하십시오.)스트림의 장점 중 하나는 코드의 구조가 동일하게 유지된다는 것입니다: 순차적 또는 동시 적이든,그것은 읽을 수있는 것처럼 유지됩니다.

코드를 병렬로 실행하려면.stream()(또는 스트림 작성자가 아닌 경우stream.parallel())대신.parallelStream()을 사용하면됩니다.

그러나 그것이 쉽기 때문에 병렬 코드가 항상 최선의 선택이라는 것을 의미하지는 않습니다. 코드 조각에 동시성을 사용하는 것이 합리적인지 항상 고려해야 합니다. 그 결정에서 가장 중요한 요소는 속도입니다:순차적 대응보다 코드를 빠르게 만드는 경우에만 동시성을 사용하십시오.

속도 질문

병렬 코드는 순차 코드가 사용하는 단일 스레드 대신 여러 스레드를 사용하여 속도 이점을 얻습니다. 스레드를 너무 많이 사용하면 코드의 성능이 실제로 저하될 수 있습니다.

선택할 스레드 수를 알려주는 몇 가지 규칙이 있습니다. 이 작업은 주로 수행하려는 작업의 종류와 사용 가능한 코어 수에 따라 다릅니다.

계산 집약적 작업은 코어 수보다 낮거나 같은 수의 스레드를 사용해야 합니다. 이 코드는 수행 할 작업을 말하지 않는 한 적용 할 수있는 경우를 알 수 없습니다. 그렇지 않으면 코어 수와 동일한 스레드 수가 기본값으로 지정됩니다.

순차 대신 코드를 병렬로 실행하는 것이 유용 할 수있는 두 가지 주요 경우가 있습니다:시간이 많이 걸리는 작업과 큰 컬렉션에서 실행되는 작업. 자바 8 은 큰 컬렉션,즉 스트림을 처리하는 새로운 방법을 가져 왔습니다. 스트림은 게으름에 의해 내장 된 효율성을 가지고:그들은 필요 이상으로 수행하지 않음으로써 자원을 절약 게으른 평가를 사용합니다. 이것은 병렬 처리와 동일하지 않으며,더 빨리 진행되는 한 자원에 신경 쓰지 않습니다. 따라서 큰 컬렉션의 경우 고전적인 병렬 처리가 필요하지 않을 것입니다.

가 비동기

자바 스크립트에서 수업

그것은 자바 개발자가 자바 스크립트를보고 뭔가를 배웠다고 말할 수있는 드문 일이지만,비동기 프로그래밍에 관해서,자바 스크립트는 실제로 바로 먼저 그것을 얻었다. 근본적으로 비동기 언어 인 자바 스크립트는 심하게 구현 될 때 얼마나 고통 스러울 수 있는지에 대한 많은 경험을 가지고 있습니다. 그것은 콜백으로 시작하고 나중에 약속에 의해 대체되었다. 약속의 중요한 이점은 두 개의”채널”이 있다는 것입니다:하나는 데이터 용이고 다른 하나는 오류 용입니다. 자바 스크립트 약속은 다음과 같이 보일 수 있습니다:

func.then(f1).catch(e1).then(f2).catch(e2);

그래서 원래 함수가 성공적인 결과를 가질 때 에프 1 이 호출되지만 오류가 발생한 경우 이자형 1 이 호출됩니다. 이것은 성공적인 트랙으로 다시 가져올 수 있습니다(에프 2),또는 다른 오류가 발생할 수(이자형 2). 데이터 트랙에서 오류 트랙으로 다시 이동할 수 있습니다.

자바 스크립트 약속의 자바 버전을 완료 가능미래라고합니다.

완성된 미래

CompletableFutureFutureCompletionStage인터페이스를 모두 구현합니다. Future사전 자바 8 은 이미 존재했지만 그 자체로는 개발자 친화적이지 않았습니다. 비동기 계산의 결과는.get()메서드를 사용하여 얻을 수 있습니다.이 메서드는 나머지를 차단하고(비동기 부분을 대부분 무의미하게 만듭니다)가능한 각 시나리오를 수동으로 구현해야했습니다. CompletionStage인터페이스를 추가하는 것은 자바에서 비동기 프로그래밍을 실행 가능하게 만든 돌파구였습니다.

CompletionStage은 약속,즉 계산이 결국 이루어질 것이라는 약속입니다. 그것은 당신이 그 완료에 실행 될 콜백을 첨부 할 수있는 방법의 무리가 포함되어 있습니다. 이제 우리는 차단하지 않고 결과를 처리 할 수 있습니다.

코드의 비동기 부분을 시작할 수 있는 두 가지 주요 메서드가 있습니다..

CompletableFuture.runAsync(() → System.out.println("Run async in completable future " + Thread.currentThread()));CompletableFuture.supplyAsync(() → 5);

콜백

이제 이러한 콜백을 추가하여supplyAsync의 결과를 처리 할 수 있습니다.

CompletableFuture.supplyAsync(() → 5).thenApply(i → i * 3).thenAccept(i → System.out.println("The result is " + i).thenRun(() → System.out.println("Finished."));

.thenApply 스트림에 대한.map함수와 비슷합니다. 위의 예에서 결과(5)에 3 을 곱합니다. 그런 다음 그 결과(15)를 파이프 아래로 더 전달합니다.

.thenAccept는 결과를 변환하지 않고 메서드를 수행합니다. 또한 결과를 반환하지 않습니다. 여기에서 콘솔에”결과 15″가 인쇄됩니다. 스트림에 대한.foreach방법과 비교할 수 있습니다.

.thenRun는 비동기 작업의 결과를 사용하지 않으며 아무 것도 반환하지 않으며 이전 단계가 완료 될 때까지Runnable를 호출 할 때까지 기다립니다.

비동기

위의 모든 콜백 메소드는 비동기 버전(thenRunAsync,thenApplyAsync등)으로도 제공됩니다. 이러한 버전은 자체 스레드에서 실행할 수 있으며 사용할ForkJoinPool을 알 수 있기 때문에 추가 제어 기능을 제공합니다.

비동기 버전을 사용하지 않으면 콜백이 모두 동일한 스레드에서 실행됩니다.

일이 잘못되면

일이 잘못되면exceptionally메서드가 예외를 처리하는 데 사용됩니다. 당신은 그것을 다시 데이터 트랙에 얻을 수있는 값을 반환하는 방법을 제공 할 수 있습니다,또는 던져(새로운)예외.

….exceptionally(ex → new Foo()).thenAccept(this::bar);

결합 및 작성

thenCompose방법을 사용하여 다중CompletableFutures을 연결할 수 있습니다. 그렇지 않으면 결과는CompletableFutures중첩됩니다. 이것은 스트림에 대해thenComposethenApplyflatMapmap처럼 만듭니다.

CompletableFuture.supplyAsync(() -> "Hello").thenCompose(s -> CompletableFuture.supplyAsync(() -> s + "World"));

CompletableFutures의 결과를 결합하려면thenCombine이라는 메서드가 필요합니다.

future.thenCombine(future2, Integer::sum).thenAccept(value → System.out.println(value));

위의 예에서 볼 수 있듯이thenCombine의 콜백 결과는 좋아하는CompletionStage방법을 모두 사용하여 일반CompletableFuture처럼 처리 할 수 있습니다.

결론

병렬 프로그래밍은 더 이상 더 빠른 코드를 찾기 위해 극복 할 수없는 장애물이 될 필요가 없습니다. 자바 8 이 될 수있는 한 간단 프로세스를 만든다,그래서 가능성이 혜택을 누릴 수있는 코드의 조각,뽑아 될 수있다,발로 모든 스레드에 비명,멀티 코어의 미래로,사실로,단지 현재 하루. 하는 내 말은:그것은 쉽게 할,그래서 그것을 시도하고 자신에 대한 장점을 볼 수 있습니다.



+