Hi, ich möchte Random parallelisieren, weil ich eine Partition mit Zufallszahlen beschreiben möchte. Dabei hab ich festgestellt, dass das Beziehen der Zufallszahlen am längsten dauert (ein Thread ist immer voll ausgelastet), und nur mit 20 MiB/s geschrieben werden kann. Daher dachte ich, es wäre klug, wenn mehrere Threads die Zufallszahlen gleichzeitig beziehen würden. Ich brauche jedoch die gleiche Sequenz der Zufallszahlen, die geschrieben werden sollen - und dann später gelesen werden sollen. Jetzt ist die Anwendung aber bei einer CPU-Last von 100% und noch langsamer als zuvor:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class USBTest {
public static class MyIter implements Iterable<Integer> {
private static final int n = 10_000;
private Deque<Integer> deque = new ArrayDeque<>(n);
private Random r = new Random(1);
ExecutorService es = null;
public MyIter() {
es = Executors.newFixedThreadPool(4);
Runnable r = new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()) {
add();
}
}
};
for (int i = 0; i < 4; i++) {
es.execute(r);
}
}
public void stop() {
if (es != null) {
es.shutdown();
}
}
private synchronized void add() {
if (deque.size() < n) {
deque.add(r.nextInt(256));
notifyAll();
}
}
private synchronized int get() {
if (deque.isEmpty()) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return deque.pollFirst();
}
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
@Override
public boolean hasNext() {
return true;
}
@Override
public Integer next() {
return get();
}
};
}
}
private static float sec(long t1, long t2) {
return (float) ((t2 - t1) / 1000.0);
}
private static float kib(long size) {
return (float) (size / 1024.0);
}
private static float mib(long size) {
return (float) (size / 1024.0 / 1024.0);
}
public static void test(String dir) throws FileNotFoundException {
MyIter mi = new MyIter();
Iterator<Integer> r = mi.iterator();
long size = 0;
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dir + "\\testfile1.txt"))) {
long t1 = System.currentTimeMillis();
for (long i = 0; true; i++) {
bos.write(r.next());
size++;
if (size % 10_000_000 == 0) {
long t2 = System.currentTimeMillis();
System.out.printf("I write %s MiB in %s MiB/s%n", mib(size), mib(size) / sec(t1, t2));
}
}
} catch (IOException e) {
}
System.out.printf("The capacity is: %s byte, %s kilobyte, %s megabyte, %s KiB, %s MiB%n", size, (float) (size / 1000.0), (float) (size / 1000.0 / 1000.0), kib(size), mib(size));
mi.stop();
mi = new MyIter();
r = mi.iterator();
size = 0;
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(dir + "\\testfile1.txt"))) {
long t1 = System.currentTimeMillis();
int b;
while ((b = bis.read()) != -1) {
size++;
if (b != r.next()) {
System.out.println("Failure!");
return;
}
if (size % 10_000_000 == 0) {
long t2 = System.currentTimeMillis();
System.out.printf("I read %s MiB in %s MiB/s%n", mib(size), mib(size) / sec(t1, t2));
}
}
long t2 = System.currentTimeMillis();
System.out.printf("I read %s MiB in %s MiB/s%n", mib(size), mib(size) / sec(t1, t2));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("The usb stick is proper!");
}
public static void main(String[] args) throws FileNotFoundException {
test("E:");
}
}
Habt ihr Ideen?