Java Swing 多线程加载图片(保证顺序一致)

Java Swing 多线程加载图片(保证顺序一致)

大二的时候做的课程设计,图片管理器,当时遇到图片很多的文件夹,加载顺序非常慢。虽然尝试用多个Thread加载图片,却无法保证图片按顺序加载。直到今天学会了使用Callable接口和Future接口,于是心血来潮实现了这个功能。

废话不多说,看代码。

多线程加载图片(核心):

package com.lin.imagemgr;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import javax.swing.ImageIcon;
import javax.swing.JLabel;

import net.coobird.thumbnailator.Thumbnails;

public class ImageMgr {
    private static ImageMgr instance = new ImageMgr();
    private ImageMgr() {}
    public static ImageMgr getInstance() {
        return instance;
    }

    //线程池
    private ExecutorService executor = Executors.newFixedThreadPool(8);

    public List<JLabel> loadImages(String path) {
        List<JLabel> images = new ArrayList<>();
        File file = new File(path);
        if (!file.isDirectory()) {
            throw new RuntimeException("need directory!");
        }
        File[] files = file.listFiles(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                //thumbnail只支持jpg??
                if (name.endsWith(".jpg")) {
                    return true;
                }
                return false;
            }
        });

        //并发加载图片,并使用Future保存加载结果
        List<Future<MyLabel>> futures = new ArrayList<>();
        for (final File f : files) {
            Future<MyLabel> future = executor.submit(() -> {
                return new MyLabel(f.getName(), f.getAbsolutePath());
            });
            futures.add(future);
        }

        //等待所有并发加载返回结果
        try {
            for (Future<MyLabel> future : futures) {
                MyLabel icon = future.get();
                images.add(icon);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        //Java8使用stream API 进行排序
        List<JLabel> sortedList = images.stream().sorted().collect(Collectors.toList());

        return sortedList;
    }

    //继承JLabel并实现Comparable接口,从而对JLabel进行排序
    private static class MyLabel extends JLabel implements Comparable<MyLabel>{
        private static final long serialVersionUID = 1L;
        private String fileName;

        public MyLabel(String fileName, String fullPath) {
            this.fileName = fileName;
            //使用thumbnailator生成缩略图
            try {
                BufferedImage bufferedImage = Thumbnails.of(fullPath)   
                .size(100, 120)
                .asBufferedImage();
                setIcon(new ImageIcon(bufferedImage));
                setPreferredSize(new Dimension(100, 120));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public int compareTo(MyLabel o) {
            int result = this.fileName.compareTo(o.fileName);
            return result;
        }



    }

}

Swing界面:

package com.lin.imagemgr;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

public class MainFrame extends JFrame{
    private static final long serialVersionUID = 1L;
    private JTextField pathField;
    private JButton showBtn;
    private JPanel contentPanel;

    public void init() {
        JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
        topPanel.setPreferredSize(new Dimension(800, 40));
        pathField = new JTextField(50);
        showBtn = new JButton("显示图片");
        topPanel.add(pathField);
        topPanel.add(showBtn);
        getContentPane().add(BorderLayout.NORTH, topPanel);
        contentPanel = new JPanel();
        contentPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
        contentPanel.setPreferredSize(new Dimension(750, 1800));
        JScrollPane jsp = new JScrollPane(contentPanel);
        getContentPane().add(BorderLayout.CENTER, jsp);

        showBtn.addActionListener((e) -> {
            try {
                loadImages();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });

        setSize(800, 650);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public void loadImages() {
        contentPanel.removeAll();
        String path = pathField.getText();
        long start = System.currentTimeMillis();
        List<JLabel> images = ImageMgr.getInstance().loadImages(path);
        for (JLabel label :images) {
            contentPanel.add(label);
        }
        contentPanel.updateUI();
        long end = System.currentTimeMillis();
        System.out.println("加载需要" + (end - start) + "毫秒!");

    }

    public static void main(String[] args) {
        new MainFrame().init();
    }

}

运行结果

这里写图片描述

这里写图片描述

在我的电脑上,加载92张图片并渲染到界面上,总共花了1568毫秒。大家可以找一个图片很多的文件夹,尝试加载大量图片的情况。

猜你喜欢

转载自blog.csdn.net/qq_21508059/article/details/78743696
今日推荐