【问题标题】:How to run process builder command as thread in java如何在java中将进程构建器命令作为线程运行
【发布时间】:2014-09-30 05:34:00
【问题描述】:

我需要在 image magick 工具的帮助下使用进程构建器在文件夹内进行图像转换。我需要在转换后删除原始文件,但是当我使用等待它需要很长时间才能完成。我使用了以下代码

          for (int h = 0; h < convimagefolder.size(); h++) {
            /* CMYK conversion for jpg and tiff and also .psd conversion*/
            destpathfinalconvs = new File(tempdir + "/" + convimagefolder.get(h));

            //  JOptionPane.showMessageDialog(null, "CMYK jpg conversion - folder assign");
            ProcessBuilder pb = new ProcessBuilder("mogrify", "-colorspace", "RGB", destpathfinalconvs.toString() + "\\" + "*.jpg");
            pb.redirectErrorStream(true);
            try {
                Process p = pb.start();
                System.out.println("CMYK to RGB jpg done for "+convimagefolder.get(h));
//                try {
//                    p.waitFor();
//                } catch (InterruptedException ex) {
//                    Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
//                }
            } catch (IOException ex) {
                Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
            }

            //  JOptionPane.showMessageDialog(null, "tif conversion - folder assign");
            ProcessBuilder pb1 = new ProcessBuilder("mogrify", "-colorspace", "RGB", destpathfinalconvs.toString() + "\\" + "*.tif");
            pb1.redirectErrorStream(true);
            try {
                Process p1 = pb1.start();
                System.out.println("cmyk tif to rgb done " + convimagefolder.get(h));
//                try {
//                    p1.waitFor();
//                } catch (InterruptedException ex) {
//                    Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
//                }
            } catch (IOException ex) {
                Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
            }

            //  JOptionPane.showMessageDialog(null, "psd conversion - folder assign");
            ProcessBuilder pb2 = new ProcessBuilder("mogrify", "-format", "jpg", destpathfinalconvs.toString() + "\\" + "*.psd[0]");
            pb2.redirectErrorStream(true);
            try {
                Process p2 = pb2.start();
                System.out.println("psd to jpg done" + convimagefolder.get(h));
//                try {
//                    p2.waitFor();
//                } catch (InterruptedException ex) {
//                    Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
//                }
            } catch (IOException ex) {
                Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
            }
            /* CMYK conversion for jpg and tiff and also .psd conversion*/


            /* tif to jpg conversion*/
            ProcessBuilder pb3 = new ProcessBuilder("mogrify", "-format", "jpg", destpathfinalconvs.toString() + "\\" + "*.tif");
            pb3.redirectErrorStream(true);
            try {
                Process p3 = pb3.start();
//                try {
//                    p3.waitFor();
//                } catch (InterruptedException ex) {
//                    Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
//                }
                System.out.println(".tif to jpg done successfully"+ convimagefolder.get(h));
            } catch (IOException ex) {
                Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(null, "Error in tif to jpg conversion " + ex.toString());

            }


            /* pdf to jpg*/
            ProcessBuilder pb4 = new ProcessBuilder("mogrify", "-format", "jpg", destpathfinalconvs.toString() + "\\" + "*.pdf");
            pb4.redirectErrorStream(true);
            try {
                Process p4 = pb4.start();
//                try {
//                    p4.waitFor();
//                } catch (InterruptedException ex) {
//                    Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
//                }
                System.out.println(".pdf to jpg done successfully"+ convimagefolder.get(h));
            } catch (IOException ex) {
                Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(null, "Error in tif to jpg conversion " + ex.toString());

            }


            /* image size reduction*/
            ProcessBuilder pb5 = new ProcessBuilder("mogrify", "-strip", "-quality", "50%", destpathfinalconvs.toString() + "\\" + "*.jpg");
            //   ProcessBuilder pb5 = new ProcessBuilder("mogrify", "-path ", destinationpath.toString(), "-strip", "-quality", "50%",  destinationpath.toString() + "\\" + "*.jpg");
            pb5.redirectErrorStream(true);
            try {
                Process p5 = pb5.start();
//                try {
//                    p5.waitFor();
//                } catch (InterruptedException ex) {
//                    Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
//                }
                System.out.println("image conversion done successfully"+ convimagefolder.get(h));
            } catch (IOException ex) {
                Logger.getLogger(DefineTask.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(null, "Error in jpg compression " + ex.toString());
            }
        }
        JOptionPane.showMessageDialog(null, "Image compression and conversion done using Image Magick");

是否可以通过线程来做到这一点。请提出任何缩短转换时间的想法

【问题讨论】:

  • 是的,这是可能的,但它不会让它更快,你仍然需要在 Thread 中运行整个块或作为一系列链式任务......它是什么你希望改进吗?
  • 在此转换之后,我正在删除文件,但是当该过程未完成时,没有任何文件被添加到我的数组列表中删除
  • 我需要减少转换时间。这里需要2-4分钟。我需要减少这个时间
  • 最好的希望是交错执行进程,以便一次可以运行多个进程,这实际上可能会增加转换时间,因为它们不会竞争机器资源...

标签: java multithreading imagemagick image-conversion


【解决方案1】:

我会看看Executors,它可以让您汇集一系列任务并让它们在一个或多个线程中自动执行...

例如...

ExecutorService service = Executors.newFixedThreadPool(7);

for (int h = 0; h < convimagefolder.size(); h++) {

    /* CMYK conversion for jpg and tiff and also .psd conversion*/
    destpathfinalconvs = new File(tempdir + "/" + convimagefolder.get(h));

    service.submit(new ProcessTask(
            "CMYK to RGB jpg done for " + convimagefolder.get(h),
            new String[]{
                "mogrify", "-colorspace", "RGB", destpathfinalconvs.toString() + "\\" + "*.jpg"}
    ));
    service.submit(new ProcessTask(
            "CMYK to RGB jpg done for " + convimagefolder.get(h),
            new String[]{
                "mogrify", "-colorspace", "RGB", destpathfinalconvs.toString() + "\\" + "*.jpg"}
    ));
    service.submit(new ProcessTask(
            "cmyk tif to rgb done " + convimagefolder.get(h),
            new String[]{
                "mogrify", "-colorspace", "RGB", destpathfinalconvs.toString() + "\\" + "*.tif"}
    ));
    service.submit(new ProcessTask(
            "psd to jpg done" + convimagefolder.get(h),
            new String[]{
                "mogrify", "-format", "jpg", destpathfinalconvs.toString() + "\\" + "*.psd[0]"}
    ));
    service.submit(new ProcessTask(
            ".tif to jpg done successfully" + convimagefolder.get(h),
            new String[]{
                "mogrify", "-format", "jpg", destpathfinalconvs.toString() + "\\" + "*.tif"
            }
    ));
    service.submit(new ProcessTask(
            ".pdf to jpg done successfully" + convimagefolder.get(h),
            new String[]{
                "mogrify", "-format", "jpg", destpathfinalconvs.toString() + "\\" + "*.pdf"
            }
    ));
    service.submit(new ProcessTask(
            "image conversion done successfully" + convimagefolder.get(h),
            new String[]{
                "mogrify", "-strip", "-quality", "50%", destpathfinalconvs.toString() + "\\" + "*.jpg"}
    ));
}

实际上Callable 任务...

public class ProcessTask implements Callable<Integer> {

    private String cmds[];
    private String name;

    public ProcessTask(String name, String[] cmds) {
        this.cmds = cmds;
        this.name = name;
    }

    @Override
    public Integer call() throws Exception {
        System.out.println("Started " + name);
        ProcessBuilder pb = new ProcessBuilder(cmds);
        pb.redirectErrorStream(true);
        Process p5 = pb.start();
        p5.waitFor();
        System.out.println("Completed " + name);
        return p5.exitValue();
    }

}

现在,如果您想等到所有任务都完成并检查它们的状态(查看谁成功完成和谁失败),您可以将所有Callables 添加到List 并使用ExecutorService#invokeAll(List),这将阻塞直到List 中的所有Callables 完成。然后,您可以遍历返回的 List 并查看是否有任何 Callables 失败(调用 Callable#get 将返回 Callable 返回的值或抛出 Callable 引发的 Exception。 ..)

另一种方法可能是,而不是在单个 Callables 中执行进程,而是创建一个引用 FileCallable,将这些添加到 ExecutorService 并在 @ 中执行每个步骤987654341@,等待每个完成,使用引用的File...

这样,当你到最后,你可以删除文件。这将允许您并行处理每个文件...

【讨论】:

  • 我试过了,它没有转换图像,同样无法删除文件,但它更快
  • 您没有做的一件事是处理来自底层Process 的输出,这可能会报告example 的错误或问题。在确定所有必需的处理完成之前,您也应该不要删除该文件...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 2019-09-24
  • 2018-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多