VM에 많은 파일을 작성해야합니다. 300.000 개 정도의 파일을 작성해야하지만, 오늘은 파일 생성을위한 작업을 잘 수행하지만 작업을 완료하는 데는 3 ~ 4 시간이 걸립니다.mutiples 스레드를 사용하여 파일 쓰기
이 병렬 스레드를 구현하는 방법을 모르겠습니다. 누군가 나를 도와주는 모범을 보입니다.
감사
VM에 많은 파일을 작성해야합니다. 300.000 개 정도의 파일을 작성해야하지만, 오늘은 파일 생성을위한 작업을 잘 수행하지만 작업을 완료하는 데는 3 ~ 4 시간이 걸립니다.mutiples 스레드를 사용하여 파일 쓰기
이 병렬 스레드를 구현하는 방법을 모르겠습니다. 누군가 나를 도와주는 모범을 보입니다.
감사
나는 당신이 멀티 스레딩에서하지만 코드의 변경의 최소 혜택을받을 수있는 방법을 일했다. SSD의에
import java.io.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Created by peter.lawrey on 30/01/15.
*/
public class ConcurrentFileWriter {
private final ThreadPoolExecutor es;
private final int maxQueueSize;
public ConcurrentFileWriter() {
this(4, 10000);
}
public ConcurrentFileWriter(int concurrency, int maxQueueSize) {
this.maxQueueSize = maxQueueSize;
es = (ThreadPoolExecutor) Executors.newFixedThreadPool(concurrency);
}
public OutputStream newFileOutputStream(final String filename) {
return new ByteArrayOutputStream() {
@Override
public void close() throws IOException {
super.close();
final ByteArrayOutputStream baos = this;
if (es.getQueue().size() > maxQueueSize)
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new AssertionError(e);
}
es.submit(new Runnable() {
public void run() {
try {
FileOutputStream fos = new FileOutputStream(filename);
fos.write(baos.toByteArray());
fos.close();
} catch (IOException ioe) {
System.err.println("Unable to write to " + filename);
ioe.printStackTrace();
}
}
});
}
};
}
public PrintWriter newPrintWriter(String filename) {
try {
return new PrintWriter(new OutputStreamWriter(newFileOutputStream(filename), "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
public void close() {
es.shutdown();
try {
es.awaitTermination(2, TimeUnit.HOURS);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
public static void main(String... args) {
long start = System.nanoTime();
ConcurrentFileWriter cfw = new ConcurrentFileWriter();
int files = 10000;
for (int i = 0; i < files; i++) {
PrintWriter pw = cfw.newPrintWriter("file-" + i);
pw.println("Hello World");
pw.close();
}
long mid = System.nanoTime();
System.out.println("Waiting for files to be written");
cfw.close();
long end = System.nanoTime();
System.out.printf("Took %.3f seconds to generate %,d files and %.3f seconds to write them to disk%n",
(mid - start)/1e9, files, (end - mid)/1e9);
}
}
이 무엇이하는 일은 당신이 지금, 당신은 단일 스레드 코드를 작성할 수 그러나 디스크에 실제 기록은 다시 지상 과제로 수행된다
Waiting for files to be written
Took 0.075 seconds to generate 10,000 files and 0.058 seconds to write them to disk
를 인쇄합니다.
참고 : 파일을 실제로 디스크에 쓸 때까지 기다리지 않으려면 close()를 호출해야합니다.
엄청난 수의 파일을 쓰는 데있어서의 문제는 많은 HDD 작업입니다. 다중 쓰레드를 사용해도 드라이브가 더 이상 쓰러지지는 않습니다. 파일을 열거 나 닫을 때마다 약 2 IO (IO 작업)를 사용합니다. HDD가 있고 80 IOPS (IOs per Second)를 지원하면 초당 40 개의 파일을 열거 나 닫을 수 있습니다. 즉 300,000 개의 파일에 대해 약 2 시간.
비교해 보면 SSD를 사용하면 1000 배 빨라진 80,000 IOPS를 얻을 수 있으며 파일을 열고 닫을 때만 8 초를 소비 할 수 있습니다.
일단 SSD로 전환하면 다중 스레드를 사용하는 것이 좋습니다. 이 작업을 수행하는 간단한 방법은 당신이에 처리 할 수있는 파일을 공급 하나 개의 스레드를 가지고 사용하기 위해 필요한이
IntStream.range(0, 300000).parallel().
.forEach(i -> createFile(i));
디스크의 I/O 작업에 대한 설명을 감사하지만 자바 6을 사용합니다.이 솔루션은 내 문제를 해결하지 못합니다. 현재 나는 나쁜 해결책 인 재귀 연산을 사용한다. ThreadPool에 대해 여러 가지 threds를 병렬로 실행하도록 설정했는데 예제가 명확하지 않습니다. – danillonc
@danillonc Java 7이 End of Public 업데이트가되기를 감안할 때 Java 8로 업그레이드하는 것이 좋습니다. Java 6에서이를 수행하는 방법을 배우는 것이 어려울 것입니다. (멀티 스레딩은 HDD에 도움이되지는 않을 것입니다.) –
I 내 프로젝트가 아니기 때문에 내 Java 버전을 업그레이드 할 수 없습니다. 이 프로젝트는 기업의 프로젝트입니다. – danillonc
같은 것을
할 수있는 8 자바 스트림 API를 사용하는 것입니다 대기열 및 대기열에서 대기 행렬을 풀고 파일을 쓰는 스레드 풀. 이를 수행하는 한 가지 방법은 간단한 제작자 소비자를 사용하는 것입니다.
다음은 예입니다. Multithreaded producer consumer in java
@ Rajasekar 감사. 나는이 예제를 보게 될 것이고, 그것은 매우 단순 해 보인다. – danillonc
일부 코드를 게시해야합니다. 대부분의 파일 입출력은'BufferedOutputStream.'을 사용하여 엄청나게 빨라질 수 있습니다. – EJP