时间:2021-05-19
大二的时候做的课程设计,图片管理器,当时遇到图片很多的文件夹,加载顺序非常慢。虽然尝试用多个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毫秒。大家可以找一个图片很多的文件夹,尝试加载大量图片的情况。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
Java中可以使用关键字synchronized进行线程同步控制,实现关键资源顺序访问,避免由于多线程并发执行导致的数据不一致性等问题。synchronized
公平锁,顾名思义,它是公平的,可以保证获取锁的线程按照先来后到的顺序,获取到锁。非公平锁,顾名思义,各个线程获取到锁的顺序,不一定和它们申请的先后顺序一致,有可
本文实例讲述了python简单文本处理的方法。分享给大家供大家参考。具体如下:由于有多线程的影响,c++项目打印出来的时间顺序不一致,导致不太好在excel中统
在上篇文章给大家介绍了java多线程的实现方式,通过本文给大家介绍java多线程实例,对java多线程感兴趣的朋友一起学习吧首先给大家说下多线程的优缺点多线程的
前言众所周知,在多线程中,因为共享全局变量,会导致资源修改结果不一致,所以需要加锁来解决这个问题,保证同一时间只有一个线程对资源进行操作但是在分布式架构中,我们