Java-使用ImageIO进行多线程 [英] Java - Multithreading with ImageIO

查看:162
本文介绍了Java-使用ImageIO进行多线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序加载缓慢,我猜这是由于开始时必须加载的图像资源量所致.我以为多线程会有所帮助,但是现在我不太确定.这是我的自动多线程方法.

    private static Thread[] t;

    private static int currentThreads;

    public static void loadWithThreads(Object[] array, IntegerRunnable r) {

        final int threads =  Runtime.getRuntime().availableProcessors();
        t = new Thread[threads];

        for (int i = 0; i < threads; i ++) {
            t[i] = new Thread("HMediaConverter") {

                final int id = currentThreads;

                int items = (array.length / threads) * currentThreads;


                @Override
                public void run() {

                    super.run();

                    for (int i = items; i < (items + (array.length / threads)); i ++) {
                        r.run(i);
                    }

                    //Recycle this thread so it can be used for another time.
                    try {
                        t[id].join();
                        lock.notifyAll();
                        currentThreads --;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }


            };
            t[i].setPriority(Thread.MAX_PRIORITY);
            t[i].start();
            currentThreads ++;
        }
    }

这是我的图像加载代码:

public static ImageIcon loadImageIcon(String path) {
    return new ImageIcon(ImageIO.read(Tools.class.getClassLoader().getResource(path));
}

肯定有一种方法可以加快速度吗?我正在非常好的Intel i5上运行它,它应该不会这么慢,所以它必须是我的代码.

解决方案

使用...加载总共113.14mb的113张图像.

public static void loadWithoutThreads(File[] array) {
    for (File file : array) {
        try {
            ImageIO.read(file);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

大约15秒

有...

public static void loadWithThreads(File[] array) {

    final int threads = Runtime.getRuntime().availableProcessors();
    t = new Thread[threads];

    CountDownLatch latch = new CountDownLatch(threads);

    for (int i = 0; i < threads; i++) {
        t[i] = new Thread("HMediaConverter") {
            final int id = currentThreads;

            int items = (array.length / threads) * currentThreads;

            @Override
            public void run() {
                try {
                    System.out.println("Starting " + id);

                    for (int i = items; i < (items + (array.length / threads)); i++) {
                        try {
                            System.out.println(i + ": " + array[i]);
                            ImageIO.read(array[i]);
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                } finally {
                    latch.countDown();
                }

            }

        };
        t[i].setPriority(Thread.MAX_PRIORITY);
        System.out.println("Start " + i);
        t[i].start();
        currentThreads++;
    }

    try {
        latch.await();
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
}

约11秒

有...

public static void loadWithExecutor(File[] images) {
    ExecutorService service = Executors.newFixedThreadPool(2);
    List<ImageLoadingTask> tasks = new ArrayList<>(images.length);
    for (File file : images) {
        tasks.add(new ImageLoadingTask(file));
    }
    try {
        List<Future<BufferedImage>> results = service.invokeAll(tasks);
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
    service.shutdown();
}

public static class ImageLoadingTask implements Callable<BufferedImage> {

    private File file;

    public ImageLoadingTask(File file) {
        this.file = file;
    }

    @Override
    public BufferedImage call() throws Exception {
        return ImageIO.read(file);
    }

}

花7秒钟左右

ExecutorService效率更高,因为当一个线程正在处理较大的文件时,另一个线程可以处理许多较小的文件.这是通过池化直到需要它们才进行任何工作的线程来实现的,从而允许一个线程执行大量的短期工作,而其他线程也很忙.您不需要等待很长时间

有关更多详细信息,请查看执行器

I have a program that loads slowly, which I guess is due to the amount of image resources I have to load at the beginning. I thought multi-threading would help, but now I'm not so sure. Here is my automatic multi-threading method.

    private static Thread[] t;

    private static int currentThreads;

    public static void loadWithThreads(Object[] array, IntegerRunnable r) {

        final int threads =  Runtime.getRuntime().availableProcessors();
        t = new Thread[threads];

        for (int i = 0; i < threads; i ++) {
            t[i] = new Thread("HMediaConverter") {

                final int id = currentThreads;

                int items = (array.length / threads) * currentThreads;


                @Override
                public void run() {

                    super.run();

                    for (int i = items; i < (items + (array.length / threads)); i ++) {
                        r.run(i);
                    }

                    //Recycle this thread so it can be used for another time.
                    try {
                        t[id].join();
                        lock.notifyAll();
                        currentThreads --;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }


            };
            t[i].setPriority(Thread.MAX_PRIORITY);
            t[i].start();
            currentThreads ++;
        }
    }

And here is my image loading code:

public static ImageIcon loadImageIcon(String path) {
    return new ImageIcon(ImageIO.read(Tools.class.getClassLoader().getResource(path));
}

Surely there is a way to speed things up? I'm running this on a perfectly good Intel i5, it shouldn't be this slow, so it must be my code.

解决方案

Loading 113 images of a total of 159.14mb with...

public static void loadWithoutThreads(File[] array) {
    for (File file : array) {
        try {
            ImageIO.read(file);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Took ~15s

With...

public static void loadWithThreads(File[] array) {

    final int threads = Runtime.getRuntime().availableProcessors();
    t = new Thread[threads];

    CountDownLatch latch = new CountDownLatch(threads);

    for (int i = 0; i < threads; i++) {
        t[i] = new Thread("HMediaConverter") {
            final int id = currentThreads;

            int items = (array.length / threads) * currentThreads;

            @Override
            public void run() {
                try {
                    System.out.println("Starting " + id);

                    for (int i = items; i < (items + (array.length / threads)); i++) {
                        try {
                            System.out.println(i + ": " + array[i]);
                            ImageIO.read(array[i]);
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                } finally {
                    latch.countDown();
                }

            }

        };
        t[i].setPriority(Thread.MAX_PRIORITY);
        System.out.println("Start " + i);
        t[i].start();
        currentThreads++;
    }

    try {
        latch.await();
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
}

took ~11s

With...

public static void loadWithExecutor(File[] images) {
    ExecutorService service = Executors.newFixedThreadPool(2);
    List<ImageLoadingTask> tasks = new ArrayList<>(images.length);
    for (File file : images) {
        tasks.add(new ImageLoadingTask(file));
    }
    try {
        List<Future<BufferedImage>> results = service.invokeAll(tasks);
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
    service.shutdown();
}

public static class ImageLoadingTask implements Callable<BufferedImage> {

    private File file;

    public ImageLoadingTask(File file) {
        this.file = file;
    }

    @Override
    public BufferedImage call() throws Exception {
        return ImageIO.read(file);
    }

}

Took ~7s

The ExecutorService is more efficient because when one thread is processing a larger file, the other can be processing a number of small files. This is achieved by pooling the threads that aren't doing any work until they are needed, allowing a thread to perform a lot of short work, while the other thread(s) are also busy. You don't need to wait as long

Have a look at Executors for more details

这篇关于Java-使用ImageIO进行多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆