简体   繁体   English

线程化会降低PC的速度,并导致java.lang.OutOfMemoryError

[英]Threading slows down the PC and causes a java.lang.OutOfMemoryError

What I am doing is making a program that constantly takes screenshots of the users desktop and saves them as long as the user wants. 我正在做的是一个程序,该程序会不断获取用户桌面的屏幕快照,并根据用户需要保存它们。 I was initially placed a call to the method that captures in a while method but that was too slow and I need as many images take as soon as possible. 最初,我调用了该方法的调用,该调用在一个while方法中捕获,但这太慢了,我需要尽可能多地拍摄图像。 What I decided to do was use threading. 我决定要做的是使用线程。

While the program is running my PC get's slow (ie mouse flashes, moves slow, ect) and when I stop the program I get the following error. 程序运行时,我的电脑运行缓慢(即,鼠标闪烁,移动缓慢等),而当我停止程序时,出现以下错误。

Exception in thread "Thread-294" java.lang.OutOfMemoryError: Java heap space
at sun.awt.windows.WRobotPeer.getRGBPixels(Unknown Source)
at java.awt.Robot.createScreenCapture(Unknown Source)
at maple.Record.run(Record.java:29)

Here is the line that produces the error. 这是产生错误的行。

img = r.createScreenCapture(new Rectangle (0, 0, width, height));

Here is my class that contains the thread. 这是包含线程的我的课程。

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.media.MediaLocator;

public class Record implements Runnable {

    Robot r;
    static int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
    static int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
    BufferedImage img;
    public static boolean stop = false;

    public void run() {

        try {

            r = new Robot();
            img = r.createScreenCapture(new Rectangle (0, 0, width, height));
            ImageIO.write(img, "png", new File(JavCapture.tmpLocation + "\\tmp\\" + System.currentTimeMillis() + ".png"));

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

    }

}

The error is produced when I am calling the JpegImagesToMovies that has been edited to work with .png files. 当我调用已被编辑为使用.png文件的JpegImagesToMovies时,会产生错误。

Please check out this link for more information on that. 请查看链接以获取更多信息。

How can I solve the problem, and how can I make the thread use less memory so that it doesn't slow the PC down. 我该如何解决该问题,以及如何使线程使用更少的内存,以免降低PC的速度。

Here is the call in the main method. 这是main方法中的调用。

do {    
    (new Thread(new Record())).start();
} while (!Record.stop);

From the looks of it you are creating a separate thread for every screenshot, this will run you out of memory very fast. 从外观来看,您将为每个屏幕截图创建一个单独的线程,这将使您很快耗尽内存。 Instead you should have a single thread that sits in loop, sleeps and takes screenshots from time to time. 取而代之的是,您应该有一个线程处于循环中,不时休眠并不时截屏。

    public class ScreenshotTaker implements Runnable {



        private volatile boolean done = false;



        public void run( ) {

            while (!done) {
            ... take screenshot...

            ...sleep ...
            }

        }

        public void setDone( ) {

            done = true;

        }

    }

You're asking for trouble, you should go for some Threadpool implementation that would limit your thread count. 您在寻求麻烦,您应该寻求一些Threadpool实现,这将限制您的线程数。 To get idea on usage, see the official tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html 要了解用法,请参阅官方教程: http : //docs.oracle.com/javase/tutorial/essential/concurrency/pools.html

As in your solution: 在您的解决方案中:

do {    
    (new Thread(new Record())).start();
} while (!Record.stop);

you create threads faster than they can process their job. 您创建线程的速度超过了他们处理任务的速度。 Basically you just say create many threads as fast as possible, there is no guarantee on count of them processed till new one is created. 基本上,您只是说要尽可能快地创建多个线程,在创建新线程之前,无法保证对它们的处理数量。 So it's just a question of time till program dies (resources are exhausted = CPU + Memory) 所以这只是程序死掉的时间问题(资源耗尽= CPU +内存)

You should limit the thread creation process here 您应该在这里限制线程的创建过程

(new Thread(new Record())).start(); 

Those threads start almost together and bloats your memory up. 这些线程几乎一起开始,使您的内存膨胀。

With so little code to go with it is hard to say, but you should definitely make the following: 仅需很少的代码就很难说了,但是您绝对应该做到以下几点:

Robot r;
BufferedImage img;

into local variables instead of instance variables. 转换为局部变量而不是实例变量。 The way you have it, the objects they refer to will be reachable for much longer than your program actually needs them. 通过这种方式,它们所引用的对象可以达到的时间将比程序实际需要的时间长得多。 That's one road to an OutOfMemoryException . 那是通往OutOfMemoryException

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM