multithreaded stamp loading

This commit is contained in:
Patrick Haßel 2023-02-26 18:24:15 +01:00
parent e3f9143a85
commit 6b7dd83149
5 changed files with 96 additions and 4 deletions

View File

@ -14,4 +14,6 @@ public class CONFIG {
public static final int STAMP_BUTTON_SIZE = 75;
public static final int STAMP_BUTTON_ICON_REAL_SIZE = STAMP_BUTTON_SIZE - STROKE_HIGHLIGHT_WIDTH * 2;
}

View File

@ -11,6 +11,7 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static de.ph87.kindermalen.CONFIG.STAMP_BUTTON_ICON_REAL_SIZE;
import static de.ph87.kindermalen.util.ImageHelper.RESIZE;
@Slf4j
@ -30,6 +31,7 @@ public class Stamp {
this.name = file.getName().substring(0, file.getName().lastIndexOf("."));
this.file = file;
this.original = ImageIO.read(file);
getSize(STAMP_BUTTON_ICON_REAL_SIZE);
log.info("Stamp loaded: {}", this);
}

View File

@ -30,7 +30,7 @@ public class StampButton extends JPanel {
MouseListener.onRelease(this, this::onRelease);
MouseListener.onEnter(this, this::onEnter);
MouseListener.onExit(this, this::onExit);
icon = stamp.getSize(STAMP_BUTTON_SIZE - STROKE_HIGHLIGHT_WIDTH * 2);
icon = stamp.getSize(STAMP_BUTTON_ICON_REAL_SIZE);
position = new Point((STAMP_BUTTON_SIZE - icon.getWidth()) / 2, (STAMP_BUTTON_SIZE - icon.getHeight()) / 2);
}

View File

@ -2,6 +2,7 @@ package de.ph87.kindermalen.tools.tool.stamp;
import de.ph87.kindermalen.drawing.Drawing;
import de.ph87.kindermalen.tools.tool.Tool;
import de.ph87.kindermalen.util.Batch;
import de.ph87.kindermalen.util.Vector;
import lombok.Getter;
import lombok.Setter;
@ -11,8 +12,10 @@ import lombok.extern.slf4j.Slf4j;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Stream;
import static de.ph87.kindermalen.util.FileHelper.SCAN_FILES;
import static de.ph87.kindermalen.util.ImageHelper.ALPHA;
@ -25,7 +28,7 @@ public class StampTool extends Tool {
private static final File STAMPS_DIR = new File("./data/stamps");
private final List<Stamp> stamps;
private List<Stamp> stamps = new ArrayList<>();
@Setter
private Stamp stamp = null;
@ -43,7 +46,12 @@ public class StampTool extends Tool {
public StampTool() {
super("Stempel");
stamps = SCAN_FILES(STAMPS_DIR).stream().map(this::load).filter(Objects::nonNull).toList();
final Stream<Supplier<Stamp>> runnables = SCAN_FILES(STAMPS_DIR).stream().map(stamp -> () -> StampTool.this.load(stamp));
try {
stamps = new Batch<>(runnables.toList()).join();
} catch (InterruptedException e) {
log.error(e.toString());
}
if (stamp == null && !stamps.isEmpty()) {
setStamp(stamps.get(0));
}

View File

@ -0,0 +1,80 @@
package de.ph87.kindermalen.util;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
@Slf4j
public class Batch<T> {
private final List<Supplier<T>> suppliers;
private final Set<Thread> threads = new HashSet<>();
private boolean stop = false;
private final List<T> results = new ArrayList<>();
public Batch(final List<Supplier<T>> suppliers) {
this.suppliers = new ArrayList<>(suppliers);
synchronized (threads) {
for (int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) {
final Thread thread = new Thread(this::threadMain, "BATCH-%03d".formatted(i));
threads.add(thread);
thread.start();
}
}
}
public void stop() {
synchronized (threads) {
stop = true;
threads.notifyAll();
}
}
public List<T> join() throws InterruptedException {
synchronized (threads) {
while (!threads.isEmpty()) {
threads.wait();
}
return results;
}
}
private void threadMain() {
try {
log.debug("Started");
while (true) {
final Supplier<T> supplier = getNext();
if (supplier == null) {
return;
}
final T result = supplier.get();
synchronized (results) {
results.add(result);
}
}
} finally {
synchronized (threads) {
threads.remove(Thread.currentThread());
threads.notifyAll();
log.debug("Terminated");
}
}
}
private Supplier<T> getNext() {
synchronized (threads) {
if (stop || suppliers.isEmpty()) {
return null;
}
return suppliers.remove(0);
}
}
}