private Map<Album, Map<ImageType, Resource>> collectAlbumTargets( Library library, final ResourceLocator resourceLocator, Collection<Album> changedAlbums) { Map<Album, Map<ImageType, Resource>> result = new HashMap<>(); for (Album album : library.getAlbums()) { Resource artworkAssetResource = album.artworkAssetResource(); if (artworkAssetResource != null) { Map<ImageType, Resource> targets = new HashMap<ImageType, Resource>(); for (ImageType type : ImageType.values()) { String imagePath = resourceLocator.getAlbumImagePath(album, type); if (imagePath != null) { Resource resource = resourceLocator.getResource(imagePath); try { if (changedAlbums.contains(album) || !resource.exists()) { resource.getParent().mkdirs(); targets.put(type, resource); } } catch (IOException e) { LOGGER.warning("Could not write image file: " + resource.getPath().toAbsolutePath()); } } } if (!targets.isEmpty()) { result.put(album, targets); } } } return result; }
public void formatImages( Library library, ResourceLocator resourceLocator, Collection<Album> changedAlbums, int maxThreads, final ProgressHandler progressHandler) { if (progressHandler != null) { progressHandler.beginTask(-1, "Preparing images..."); } final Map<Album, Map<ImageType, Resource>> albumTargets = collectAlbumTargets(library, resourceLocator, changedAlbums); if (progressHandler != null) { progressHandler.endTask(); } List<Album> albums = new ArrayList<>(albumTargets.keySet()); int numberOfAlbumsPerTask = 10; int numberOfAlbums = albums.size(); int numberOfThreads = Math.min( 1 + (numberOfAlbums - 1) / numberOfAlbumsPerTask, Math.min(maxThreads, Runtime.getRuntime().availableProcessors())); if (progressHandler != null) { progressHandler.beginTask(numberOfAlbums, "Formatting images..."); } final int progressModulo = numberOfAlbums < 200 ? 10 : numberOfAlbums < 1000 ? 50 : 100; if (numberOfThreads > 1) { // run on multiple threads if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer("Parallel: #threads = " + numberOfThreads); } ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads); final AtomicInteger atomicCount = new AtomicInteger(); for (int start = 0; start < numberOfAlbums; start += numberOfAlbumsPerTask) { final Collection<Album> albumsSlice = albums.subList(start, Math.min(numberOfAlbums, start + numberOfAlbumsPerTask)); executor.execute( new Runnable() { @Override public void run() { for (Album album : albumsSlice) { formatImages(album.artworkAssetResource(), albumTargets.get(album)); int count = atomicCount.getAndIncrement() + 1; if (progressHandler != null && count % progressModulo == 0) { progressHandler.progress(count, String.format("#albums = %4d", count)); } } } }); } executor.shutdown(); try { executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); } catch (InterruptedException e) { LOGGER.warning("Interrupted: " + e.getMessage()); } } else { // run on current thread int count = 0; for (Album album : albums) { formatImages(album.artworkAssetResource(), albumTargets.get(album)); count++; if (progressHandler != null && count % progressModulo == 0) { progressHandler.progress(count, String.format("#albums = %4d", count)); } } } if (progressHandler != null) { progressHandler.endTask(); } }