2017-10-29 21 views
2

D 설명서는 약간 이해하기 어렵습니다. 어떻게 D에서 다음 Java 코드를 얻을 수 있습니까?D 언어로 된 ExecutorService에 해당 하시겠습니까?

ExecutorService service = Executors.newFixedThreadPool(num_threads); 

for (File f : files) { 
    service.execute(() -> process(f)); 
} 

service.shutdown(); 
try { 
    service.awaitTermination(24, TimeUnit.HOURS); 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 

나는 std.parallelism 또는 std.concurrency를 사용하거나 표준 라이브러리에서 사용할 수없는이 기능입니다겠습니까.

답변

4

게시 한 예는 std.parallelism으로 가장 잘 표현됩니다. 당신은 parallel 헬퍼 함수를 ​​사용할 수 있는데, foreach에서 사용될 때 스레드 번호 (작업자 크기)가 totalCPUs - 1 인 스레드 풀에서 foreach 루프의 본문을 자동으로 실행합니다. 임의의 병렬 코드를 수행하기 전에 (기본 코드를 시작할 때 가장 잘 수행) 또는 사용자 정의 taskPool을 사용하여 defaultPoolThreads = x;을 설정하여이 기본값을 변경할 수 있습니다.

은 기본적으로 다음 코드는 다음에 번역 것 :

foreach (f; files.parallel) { 
    process(f); // or just paste what should be done with f in here if it matters 
} 

std.parallelism는 멀티 스레딩의 높은 수준의 구현입니다. 작업 풀만 갖고 싶다면 new TaskPool() (선택적 인수로 작업자 수와 함게)을 생성 한 다음 service.parallel(files)을 사용하여 위와 동일하게 수행 할 수 있습니다.

또는 당신은 시간 제한을 구현할 수 있도록 할

foreach (f; files) { 
    service.put!process(f); 
} 
service.finish(true); // true = blocking 
// you could also do false here in a while true loop with sleeps to implement a timeout 

사용하여 작업을 많이 대기열 수 있습니다.

위의 코드를 처리하기 때문에 병렬을 사용하는 것이 좋지만 + 각 스레드는 로컬 스택에 액세스 할 수있는 저장소를 제공하므로 일반적인 비 병렬 foreach 루프와 똑같이 사용할 수 있습니다. 문서에

사이드 노트/설명 : 당신이 당신의 예제를 사용하는 것이없는 것을 불구하고

std.concurrency은 매우 유용합니다. 거기에는 강력한 메시징 API로 새 스레드를 생성하는 스폰 기능이 있습니다. 메시징 API (보내기 및 받기)를 사용하면 소켓, 파일 또는 기타 해결 방법을 사용하지 않고 스레드간에 전달되는 스레드 안전 값을 구현할 수 있습니다.

작업 (메시징 API가있는 스레드)이 있고 receive을 호출하면 전달 된 시간 초과가 완료되거나 다른 스레드가 작업의 send 함수를 호출 할 때까지 대기합니다. 예를 들어 수신을 사용하여 항상 대기하는 파일 로딩 대기열 작업을 가질 수 있습니다. UI는 로딩 대기열에 파일을 저장하고 (단지 send를 한 번 이상 호출하여)이 파일에서 작업하고 메인 루프에서 시간 초과를 사용하여 수신하는 UI 작업으로 다시 보낼 수 있습니다.

std.concurrency도 단일 스레드에서 스레드 스타일 프로그래밍을 수행하는 데 사용할 수있는 FiberScheduler을 가지고 있습니다. 예를 들어, 그리기 및 입력 처리를 수행하는 UI가 있고 모든 종류의 작업을 수행하는 경우 모든 틱의 주 루프에서 FiberScheduler를 호출하면 현재 실행중인 모든 작업이 마지막으로 중단 된 곳에서 계속됩니다 (yield 호출). 이는 이미지 생성기가 오랜 시간이 걸리지 만 UI를 너무 오랫동안 차단하지 않으므로 yield()을 호출 할 때마다 반복적으로 호출되어 생성기의 실행을 중지하고 메인 루프.

섬유가 작동하지 않을 때 스레드 주위를 통과 할 수도 있으므로 std.parallelism 및 사용자 정의 FiberScheduler 구현의 스레드 풀을 가질 수 있으며 예를 들어 웹 서버에서 유용 할 수있는로드 균형 조정을 수행 할 수 있습니다.

당신이 정확히 스레드와 동일하게 작동 core.thread에서 Fiber 클래스를 상속 할 수있는 FiberScheduler없이 섬유를 생성하고 원시 그들에게 전화 (및 마무리 상태를 확인하고 사용자 정의 스케줄러 구현에서 제거)하려면, 기다리거나 CPU 집중적 인 섹션에 있다고 생각할 때마다 Fiber.yield()를 호출하면됩니다.

대부분의 API가 Fibers 용으로 제작되지 않았기 때문에 Fibers를 사용하지 않을 수 있으므로 Fibers를 사용하는 API를 사용하고 싶습니다. 예를 들어, vibe.d에는 광섬유 기반 기능이 많이 있지만 사용자 정의 std.concurrency 구현이 있으므로이를 알아야합니다.

질문에 다시 돌아 오려면 TaskPool 또는 특별한 경우 parallel 기능이 필요합니다. "섬유 그들은 심지어 스레드 주위에 전달 될 수있는 실행되지 않을 경우"

https://dlang.org/phobos/std_parallelism.html#.parallel https://dlang.org/phobos/std_parallelism.html#.TaskPool.parallel

+0

어디에서 이것에 대해 찾을 수 있습니까? 나는 섬유가 다른 실에 전달 될 수 없다고 생각했다. – Patric

+2

@Patric https://dlang.org/phobos/core_thread.html#.Fiber "파이버는 현재 실행되지 않는 한 스레드간에 자유롭게 전달 될 수 있습니다." – WebFreak001