我试图用Java ImageIO
复制大量图像。每个副本都会调整原始图片的大小。由于图像集的大小很大(60,000)。我尝试使用多线程来解决问题。这里是代码:产生多线程图像的java.lang.OutOfMemory异常
package generate.image
import scala.util.Random._
import scala.math._
import java.io.File
import java.io.PrintWriter
import java.util.concurrent.{ExecutorService, TimeUnit, Executors}
import java.awt.Image
import java.awt.image.BufferedImage
import javax.imageio.ImageIO
class ImageResizer{
def resizeImage(srcImgPath: String, distImgPath: String, width: Int, height: Int){
val srcFile: File = new File(srcImgPath)
val srcImg: Image = ImageIO.read(srcFile)
val buffImg: BufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
buffImg.getGraphics().drawImage(
srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0,
0, null
)
ImageIO.write(buffImg, "JPEG", new File(distImgPath))
}
}
class ImageWorker(imgSrc: String, imgName: String, width: Int, height: Int) extends Runnable{
override def run(): Unit = {
val resizer = new ImageResizer()
resizer.resizeImage(imgSrc, imgName, width, height);
}
}
object ImageGenerate {
def main(args:Array[String]): Unit = {
// parameters
val dirName = args(0)
val images = new File(dirName).listFiles.filter(_.getName.endsWith(".JPEG"))
val imgCnt = images.length
// threadpool
val pool = Executors.newFixedThreadPool(25)
// copy with norm
for(i <- 0 until imgCnt){
for(cnt <- 1 to 20){
val width = nextInt(200) + 300
val height = nextInt(200) + 300
val imgSrc: String = images(i).getAbsolutePath
val imgName: String = "img/%s_%d_%d_%d.JPEG".format(splitFilename(images(i).getName), width, height, cnt)
pool.execute(new ImageWorker(imgSrc, imgName, width, height))
}
}
pool.shutdown()
pool.awaitTermination(Long.MaxValue, TimeUnit.NANOSECONDS)
}
// split file name
def splitFilename(fileName: String) = {
fileName.substring(0, fileName.lastIndexOf("."))
}
}
ImageResizer
复制工作。它将图像读入BufferedImage
,将其重新调整为新的BufferedImage
,最后写入JPEG
文件。
ImageWorker
线程是否工作。它由ExecuteServive
中的工作线程执行。
ImageGenerate
做调度工作。它读取args(0)
(第一个参数)中的所有图像文件,生成新的随机宽度和高度,并将新作业提交至pool
。
编译并运行:scalac ImageGenerate.scala
scala generate.image.ImageGenerate test
。图像的大小平均为150kb。
正在运行,程序将引发java.lang.OutOfMemoryError
。 有时,出现Exception in thread "pool-1-thread-36" java.lang.OutOfMemoryError: GC overhead limit exceeded
错误。
如果我设置参数-J-Xmx2048m
,程序将平稳运行。但是,我只运行400个图像。我的代码有没有优化?
感谢您分享您的想法,祝好。
感谢您分享您的想法。我认为我向线程池提交的任务不是流量控制的。当ExecuteService中有太多任务正在等待时,内存就会耗尽。因此,我使用信号量来限制提交的速度。它的工作很多。 – jiexray