We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
Page Index Toggle Pages: 1
multithread (Read 7986 times)
multithread
Mar 8th, 2008, 4:36pm
 
anyone know how to do the multithread in processing, especially deal with images?

I have made a program which link & display flickr image for some selective criteria, however it takes around 2 mintues to load all the 49 images. during the waiting period, the screen actully freeze.

code sample as below, just wonder if multithread approach can help to solve the problem. thanks

====
 PImage images[] = new PImage[photos.countChildren()];
    XMLElement photo;
   for (int i = 0; i < photos.countChildren() && i <    imageCount ; i++) {  
     photo = photos.getChild(i);
     String url = "http://farm" +
     photo.getAttribute("farm") + ".static.flickr.com/" +
     photo.getAttribute("server") + "/" +
     photo.getAttribute("id") + "_" +
     photo.getAttribute("secret") + "_s.jpg";    
     images[i] = loadImage(url);
======
then display the image using the standard way
image(images[i]...)
Re: multithread
Reply #1 - Mar 8th, 2008, 7:51pm
 
You'll have to write a class that implements the Runnable interface, then do all the loading in there. The thread will then run concurrently with the regular draw() loop. If you have a counter variable inside the loader class you can use that to display a progress bar or confirm that the loading is done.

Here are some references:
http://www.javaworld.com/javaworld/jw-04-1996/jw-04-threads.html
http://www.janeg.ca/scjp/threads/runnable.html
http://www.exampledepot.com/egs/java.lang/BasicThread.html

The following code will create a basic thread:

Code:
class BasicThread2 implements Runnable {
// This method is called when the thread runs
public void run() {
}
}

// Create the object with the run() method
Runnable runnable = new BasicThread2();

// Create the thread supplying it with the runnable object
Thread thread = new Thread(runnable);

// Start the thread
thread.start();
Re: multithread
Reply #2 - Mar 9th, 2008, 3:43am
 
Actually I already have the method in loading the images, sample code like this:

void fetchFlicker(String tags) {
   PImage images[] = new PImage[photos.countChildren()];
    XMLElement photo;
   for (int i = 0; i < photos.countChildren() && i <    imageCount ; i++) {  
photo = photos.getChild(i);
String url = "http://farm" +
photo.getAttribute("farm") + ".static.flickr.com/" +
photo.getAttribute("server") + "/" +
photo.getAttribute("id") + "_" +
photo.getAttribute("secret") + "_s.jpg";    
images[i] = loadImage(url);  
 
}
===========

I should write the class include this method or I cannto have another method within the class and need to re-deine all the variable?

Regarding creating object e.g Runnable runnable = new BasicThread2(); , where I should put those code (say under which method, or I just simply put at the end of my code?)

thx
Re: multithread
Reply #3 - Mar 9th, 2008, 2:03pm
 
I went and wrote up a working example for you, it leaves out the Flickr stuff but does basic multi-threaded loading. It should be enough of a template if you already know how to do the Flickr part of things.

I also posted it here: ThreadImageLoader.pde

Code:
// ThreadImageLoader.pde - Multi-threaded loading of images.
// The ImageLoader class can be used as a template for creating
// a separate thread for loading images, leaving your main sketch
// free to do other things.
//
// Marius Watz - http://workshop.evolutionzone.com/

ImageLoader loader;
Thread loadThread;
PFont fnt;

void setup() {
size(450,125);

loader=new ImageLoader();
loadThread=new Thread(loader);

loader.loadImg(
"http://farm3.static.flickr.com/2292/2317266674_77180fff63_s.jpg");
loader.loadImg(
"http://farm3.static.flickr.com/2131/2317257856_f9e9057000_s.jpg");
loader.loadImg(
"http://farm4.static.flickr.com/3250/2317275004_319ba43b1c_s.jpg");
loader.loadImg(
"http://farm3.static.flickr.com/2194/2317241464_43ebe23c0f_s.jpg");
loader.loadImg(
"http://farm3.static.flickr.com/2046/2304190351_f96852859d_s.jpg");
loader.loadImg(
"http://farm3.static.flickr.com/2069/2304970048_00d04a818d_s.jpg");

loadThread.start();
fnt=createFont("Courier",18,false);
}

void draw() {
background(0);
textFont(fnt);
noStroke();

fill(255);
text("Remaining to load: "+loader.remaining,10,20);

int x=0;
for(int i=0; i< loader.num; i++) {
PImage tmp=loader.getImage(i);
if(tmp!=null) {
image(tmp, x,50);
x=x+tmp.width;
}
}
}

void stop() {
loader.loadDone=true;
super.stop();
}

class ImageLoader implements Runnable {
ImageURL img[];
int num,remaining;
boolean loadDone=false;

public ImageLoader() {
img=new ImageURL[100];
num=0;
remaining=0;
}

void loadImg(String _url) {
// expand array if necessary
if(num==img.length) img=(ImageURL[])expand(img);

img[num++]=new ImageURL(_url);
remaining++;
}

public PImage getImage(int id) {
// return null if incorrect ID, image not loaded or error occurred
if(img[id]==null || !img[id].loaded || img[id].error)
return null;

return img[id].img;
}

public void run() {
int loadID=0;

// loop run() until loadDone is set to true
while(!loadDone) {

// find an image to load
loadID=0;
if(num>0) do {
if(img[loadID].loaded) loadID++;
else if(img[loadID]!=null) {
img[loadID].load(); // load image
remaining--; // one less remaining to load
break; // exit do loop;
}
} while(loadID< num);

try {
loadThread.sleep(500);
} catch(InterruptedException e) {
e.printStackTrace();
}
}

println("Loader thread exiting.");
}
}

class ImageURL {
PImage img;
boolean loaded=false,error=false;
String url;

public ImageURL(String _url) {
url=_url;
}

void load() {
println("nLoading image: "+url);
img=loadImage(url);
if(img==null) error=true;
loaded=true;
if(error) println("Error occurred when loading image.");
else println("Load successful. "+
"Image size is "+img.width+"x"+img.height+".");
}
}
Re: multithread
Reply #4 - Mar 10th, 2008, 7:17pm
 
it works perfectly fine, many thanks of your help.

code is real technical, what does this mean?
loadThread.sleep(500);
Re: multithread
Reply #5 - Apr 17th, 2010, 4:41pm
 
Really confused as to why loadThread.start() comes after the calls to loader.loadImg(...).  When loadThread.start() is moved above the loader.loadImg statements, it throws a NullPointerException.  Just seems counterintutive that you could call methods of a class which is supposedly running in a different thread before that thread is started?

Thanks,
Mike
Re: multithread
Reply #6 - Apr 19th, 2010, 1:07am
 
ImageLoader is still a regular Java class, so you can call its methods on the main thread as well.
loadImg()'s name isn't well chosen, as it doesn't really load the images but just add them to a list. It is actually part of the setup of the class, that's why it is called before running the thread.
I would have named it addImg() or even just add() (since the purpose of the class is clear).

To answer soon/freeHand's old question, sleep(500) just waits for half a second in the current thread, perhaps to avoid loading the CPU too much.
Note that sleep() is a static method, so it is better to call it with Thread.sleep(), calling a static method with a class instance is seen as bad practice (some compilers warn against that).
Page Index Toggle Pages: 1