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;
69+ import java.util.concurrent.atomic.AtomicInteger;
6670import java.util.regex.*;
6771import java.util.zip.*;
6872
@@ -5431,9 +5435,10 @@ public PImage loadImage(String filename) {
54315435 */
54325436 public PImage loadImage(String filename, String extension) { //, Object params) {
54335437
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)) {
5438+ // awaitAsyncSaveCompletion() has to run on the main thread, because P2D
5439+ // and P3D call GL functions. If this runs on background, requestImage()
5440+ // already called awaitAsyncSaveCompletion() on the main thread.
5441+ if (g != null && !Thread.currentThread().getName().startsWith(REQUEST_IMAGE_THREAD_PREFIX)) {
54375442 g.awaitAsyncSaveCompletion(filename);
54385443 }
54395444
@@ -5561,8 +5566,12 @@ public PImage loadImage(String filename, String extension) { //, Object params)
55615566 }
55625567
55635568
5569+ static private final String REQUEST_IMAGE_THREAD_PREFIX = "requestImage";
5570+ // fixed-size thread pool used by requestImage()
5571+ ExecutorService requestImagePool;
5572+
5573+
55645574 public PImage requestImage(String filename) {
5565- // return requestImage(filename, null, null);
55665575 return requestImage(filename, null);
55675576 }
55685577
@@ -5596,62 +5605,17 @@ public PImage requestImage(String filename, String extension) {
55965605 g.awaitAsyncSaveCompletion(filename);
55975606 }
55985607 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;
56295608
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;
5609+ // if the image loading thread pool hasn't been created, create it
5610+ if (requestImagePool == null) {
5611+ ThreadFactory factory = new ThreadFactory() {
5612+ public Thread newThread(Runnable r) {
5613+ return new Thread(r, REQUEST_IMAGE_THREAD_PREFIX);
5614+ }
5615+ };
5616+ requestImagePool = Executors.newFixedThreadPool(4, factory);
56445617 }
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-
5618+ requestImagePool.execute(() -> {
56555619 PImage actual = loadImage(filename, extension);
56565620
56575621 // An error message should have already printed
@@ -5669,31 +5633,11 @@ public void run() {
56695633 vessel.pixelHeight = actual.height;
56705634 vessel.pixelDensity = 1;
56715635 }
5672- requestImageCount-- ;
5673- }
5636+ }) ;
5637+ return vessel;
56745638 }
56755639
56765640
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-
56975641 /**
56985642 * Use Java 1.4 ImageIO methods to load an image.
56995643 */
0 commit comments