6262import java.text.*;
6363import java.util.*;
6464import java.util.concurrent.BlockingQueue;
65+ import java.util.concurrent.ExecutorService;
66+ import java.util.concurrent.Executors;
6567import java.util.concurrent.LinkedBlockingQueue;
68+ import java.util.concurrent.ThreadFactory;
6669import java.util.regex.*;
6770import java.util.zip.*;
6871
@@ -5431,9 +5434,10 @@ public PImage loadImage(String filename) {
54315434 */
54325435 public PImage loadImage(String filename, String extension) { //, Object params) {
54335436
5434- // await... has to run on the main thread, because P2D and P3D call GL functions
5435- // If this runs on background, requestImage() already called await... on the main thread
5436- if (g != null && !Thread.currentThread().getName().startsWith(ASYNC_IMAGE_LOADER_THREAD_PREFIX)) {
5437+ // awaitAsyncSaveCompletion() has to run on the main thread, because P2D
5438+ // and P3D call GL functions. If this runs on background, requestImage()
5439+ // already called awaitAsyncSaveCompletion() on the main thread.
5440+ if (g != null && !Thread.currentThread().getName().startsWith(REQUEST_IMAGE_THREAD_PREFIX)) {
54375441 g.awaitAsyncSaveCompletion(filename);
54385442 }
54395443
@@ -5561,8 +5565,12 @@ public PImage loadImage(String filename, String extension) { //, Object params)
55615565 }
55625566
55635567
5568+ static private final String REQUEST_IMAGE_THREAD_PREFIX = "requestImage";
5569+ // fixed-size thread pool used by requestImage()
5570+ ExecutorService requestImagePool;
5571+
5572+
55645573 public PImage requestImage(String filename) {
5565- // return requestImage(filename, null, null);
55665574 return requestImage(filename, null);
55675575 }
55685576
@@ -5596,62 +5604,17 @@ public PImage requestImage(String filename, String extension) {
55965604 g.awaitAsyncSaveCompletion(filename);
55975605 }
55985606 PImage vessel = createImage(0, 0, ARGB);
5599- AsyncImageLoader ail =
5600- new AsyncImageLoader(filename, extension, vessel);
5601- ail.start();
5602- return vessel;
5603- }
5604-
5605-
5606- // /**
5607- // * @nowebref
5608- // */
5609- // public PImage requestImage(String filename, String extension, Object params) {
5610- // PImage vessel = createImage(0, 0, ARGB, params);
5611- // AsyncImageLoader ail =
5612- // new AsyncImageLoader(filename, extension, vessel);
5613- // ail.start();
5614- // return vessel;
5615- // }
5616-
5617-
5618- /**
5619- * By trial and error, four image loading threads seem to work best when
5620- * loading images from online. This is consistent with the number of open
5621- * connections that web browsers will maintain. The variable is made public
5622- * (however no accessor has been added since it's esoteric) if you really
5623- * want to have control over the value used. For instance, when loading local
5624- * files, it might be better to only have a single thread (or two) loading
5625- * images so that you're disk isn't simply jumping around.
5626- */
5627- public int requestImageMax = 4;
5628- volatile int requestImageCount;
56295607
5630- private static final String ASYNC_IMAGE_LOADER_THREAD_PREFIX = "ASYNC_IMAGE_LOADER";
5631-
5632- class AsyncImageLoader extends Thread {
5633- String filename;
5634- String extension;
5635- PImage vessel;
5636-
5637- public AsyncImageLoader(String filename, String extension, PImage vessel) {
5638- // Give these threads distinct name so we can check whether we are loading
5639- // on the main/background thread; for now they are all named the same
5640- super(ASYNC_IMAGE_LOADER_THREAD_PREFIX);
5641- this.filename = filename;
5642- this.extension = extension;
5643- this.vessel = vessel;
5608+ // if the image loading thread pool hasn't been created, create it
5609+ if (requestImagePool == null) {
5610+ ThreadFactory factory = new ThreadFactory() {
5611+ public Thread newThread(Runnable r) {
5612+ return new Thread(r, REQUEST_IMAGE_THREAD_PREFIX);
5613+ }
5614+ };
5615+ requestImagePool = Executors.newFixedThreadPool(4, factory);
56445616 }
5645-
5646- @Override
5647- public void run() {
5648- while (requestImageCount == requestImageMax) {
5649- try {
5650- Thread.sleep(10);
5651- } catch (InterruptedException e) { }
5652- }
5653- requestImageCount++;
5654-
5617+ requestImagePool.execute(() -> {
56555618 PImage actual = loadImage(filename, extension);
56565619
56575620 // An error message should have already printed
@@ -5669,31 +5632,11 @@ public void run() {
56695632 vessel.pixelHeight = actual.height;
56705633 vessel.pixelDensity = 1;
56715634 }
5672- requestImageCount-- ;
5673- }
5635+ }) ;
5636+ return vessel;
56745637 }
56755638
56765639
5677- // done internally by ImageIcon
5678- // /**
5679- // * Load an AWT image synchronously by setting up a MediaTracker for
5680- // * a single image, and blocking until it has loaded.
5681- // */
5682- // protected PImage loadImageMT(Image awtImage) {
5683- // MediaTracker tracker = new MediaTracker(this);
5684- // tracker.addImage(awtImage, 0);
5685- // try {
5686- // tracker.waitForAll();
5687- // } catch (InterruptedException e) {
5688- // //e.printStackTrace(); // non-fatal, right?
5689- // }
5690- //
5691- // PImage image = new PImage(awtImage);
5692- // image.parent = this;
5693- // return image;
5694- // }
5695-
5696-
56975640 /**
56985641 * Use Java 1.4 ImageIO methods to load an image.
56995642 */
0 commit comments