gpt4 book ai didi

java - 为什么我的Java程序启动后性能会明显下降?

转载 作者:搜寻专家 更新时间:2023-10-31 08:25:34 24 4
gpt4 key购买 nike

我正在编写一个小型 Java 应用程序来分析大量图像文件。目前,它通过平均图像中每个像素的亮度并将其与文件夹中的其他图像进行比较来找到文件夹中最亮的图像。

有时,我在启动后立即获得 100 多张图片/秒的速率,但这几乎总是下降到 < 20 张图片/秒,我不确定为什么。当它在 100+ 图像/秒时,CPU 使用率是 100%,但随后下降到 20% 左右,这似乎太低了。

这是主类:

public class ImageAnalysis {

public static final ConcurrentLinkedQueue<File> queue = new ConcurrentLinkedQueue<>();
private static final ConcurrentLinkedQueue<ImageResult> results = new ConcurrentLinkedQueue<>();
private static int size;
private static AtomicInteger running = new AtomicInteger();
private static AtomicInteger completed = new AtomicInteger();
private static long lastPrint = 0;
private static int completedAtLastPrint;

public static void main(String[] args){
File rio = new File(IO.CAPTURES_DIRECTORY.getAbsolutePath() + File.separator + "Rio de Janeiro");

String month = "12";

Collections.addAll(queue, rio.listFiles((dir, name) -> {
return (name.substring(0, 2).equals(month));
}));

size = queue.size();

ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);

for (int i = 0; i < 8; i++){
AnalysisThread t = new AnalysisThread();
t.setPriority(Thread.MAX_PRIORITY);
executor.execute(t);
running.incrementAndGet();
}
}

public synchronized static void finished(){
if (running.decrementAndGet() <= 0){

ImageResult max = new ImageResult(null, 0);

for (ImageResult r : results){
if (r.averageBrightness > max.averageBrightness){
max = r;
}
}

System.out.println("Max Red: " + max.averageBrightness + " File: " + max.file.getAbsolutePath());
}
}

public synchronized static void finishedImage(ImageResult result){
results.add(result);
int c = completed.incrementAndGet();

if (System.currentTimeMillis() - lastPrint > 10000){
System.out.println("Completed: " + c + " / " + size + " = " + ((double) c / (double) size) * 100 + "%");
System.out.println("Rate: " + ((double) c - (double) completedAtLastPrint) / 10D + " images / sec");
completedAtLastPrint = c;

lastPrint = System.currentTimeMillis();
}
}

}

和线程类:

public class AnalysisThread extends Thread {

@Override
public void run() {
while(!ImageAnalysis.queue.isEmpty()) {
File f = ImageAnalysis.queue.poll();

BufferedImage image;
try {
image = ImageIO.read(f);

double color = 0;
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
//Color c = new Color(image.getRGB(x, y));
color += image.getRGB(x,y);
}
}

color /= (image.getWidth() * image.getHeight());

ImageAnalysis.finishedImage((new ImageResult(f, color)));

} catch (IOException e) {
e.printStackTrace();
}
}

ImageAnalysis.finished();
}
}

最佳答案

您似乎混淆了使用线程池和创建自己的线程。我建议你使用 on 或 other。事实上我建议你只使用固定线程池

最有可能发生的事情是您的线程收到异常,该异常正在丢失但杀死了杀死线程的任务。

我建议您只使用线程池,不要尝试创建自己的线程或队列,因为这就是 ExecutorService为你做。对于每个任务,将其提交到池中,每个图像一个,如果您不打算检查任何任务的错误,我建议您捕获所有 Throwable 并记录它们,否则您可能会得到一个 RuntimeExcepionError 并且不知道发生了什么。

如果您使用的是 Java 8,则更简单的方法是使用 parallelStream()。您可以使用它来同时分析图像并收集结果,而无需划分工作和收集结果。例如

List<ImageResults> results = Stream.of(rio.listFiles())
.parallel()
.filter(f -> checkFile(f))
.map(f -> getResultsFor(f))
.list(Collectors.toList());

关于java - 为什么我的Java程序启动后性能会明显下降?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34967845/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com