If you are looking for a tutorial about using threads in Processing, I’ve adapted this page on the Processing wiki:
http://wiki.processing.org/w/Threading
Examples:
- simplethreads.zip, SimpleThread.java, ThreadDriver.java
- newsreader.zip, XMLNewsChecker.java, CheckThread.java, a2z package
- Applet source: threads_news.zip, nothreads_news.zip
- a2z Processing library: a2z.jar (required for above applets)
- Simple Processing Event library: pevent.jar, Library source: pevent.zip, Applet source: simple_eventlib.zip
- Processing NewsReader Event library: news.jar, Library source: news.zip, Applet source: news_event.zip
Related:
Exercises (optional):
- Rewrite the spider so that each URL request is its own thread.
- Recreate one of your previous exercises as a Processing library.
Threading
We’re quite familiar with the idea of writing a program that follows a specific sequence of steps as outlined in, say, a main() function. A Thread is also a series of steps with a beginning, a middle, and an end. A thread’s sequence, however, can run independently of the main program. In fact, we can launch any number of threads at one time and they will all run concurrently. Visit the Java site for a more involved explanation.
This is incredibly useful when it comes to data mining, as we can have separate threads retrieving different pieces of information from the network. If one gets stuck or has an error, the entire program won’t grind to a halt, since the error only stops that individual thread. To create independent, asynchronous threads, we simply extend the Thread class.
public class SimpleThread extends Thread { |
It’s useful to include a few fields describing the thread’s properties. In this example, we’ll use a boolean variable to indicate whether the thread is running or not, a integer to count how many times the thread has executed its loop, a String to give the thread an ID, and an integer to hold the number of milliseconds in between each execution. The constructor will initialize these values:
private boolean running; // Is the thread running? Yes or no? private int wait; // How many milliseconds should we wait in between executions? private String id; // Thread name private int count; // counter // Constructor, create the thread // It is not running by default public SimpleThread (int w, String s){ wait = w; running = false; id = s; count = 0; } |
We are then going to override two functions from the parent Thread class:
- start() — Start causes the thread to begin its execution. The Java Virtual Machine will call the run method for you, so make sure to include super.start(). We aren’t required to override this method, but it’s useful since we may want our own custom code to execute when the thread begins.
- run() — Nothing happens in the parent version of this function. It’s up to us to write code for whatever we want the thread to do when it runs. When the end of this function is reached, the thread ends. To keep it running over a period of time, a while loop (testing the running variable) is used.
// Overriding "start()" public void start () { // Set running equal to true running = true; // Print messages System.out.println("Starting thread (will execute every " + wait + " milliseconds.)"); // Do whatever start does in Thread, don't forget this! super.start(); } // We must implement run, this gets triggered by start() public void run () { while (running && count < 10){ System.out.println(id + ": " + count); count++; // Ok, let's wait for however long we should wait try { sleep((long)(wait)); } catch (Exception e) { } } System.out.println(id + " thread is done!"); // The thread is done when we get to the end of run() } |
Finally, it’s useful to create a quit() method, in case we want to interrupt the thread and stop it. (Note that stop() is now deprecated).
// Our method that quits the thread public void quit() { System.out.println("Quitting."); running = false; // Setting running to false ends the loop in run() interrupt(); // in case the thread is waiting. . . } } |
Once we've completed our Thread class, creating and running threads is easy!
SimpleThread thread1 = new SimpleThread(1000,"cat"); SimpleThread thread2 = new SimpleThread(1500,"dog"); thread1.start(); thread2.start(); |
Here's a more sophisticated example that involves reading the Google news RSS feed in a thread.
Synchronized Threads
Writing an independent thread is easy, nevertheless, there are often times where one needs to access and manipulate information inside a thread externally (perhaps in the "main" program, or another thread, etc.) This problem occurs in data visualization programs, where we might require that an animation driven by data from the network runs smoothly, without having to pause and wait each time that data reloads. Let's look at this applet:

A few things have changed. For example, we have added a boolean variable "available" to indicate to the main program when the thread has completed loading a new set of headlines.
private boolean available; // Is new news available? |
At the end of the "check()" method, which reads the news feed, available is set to true:
private synchronized void check() { headlines = new ArrayList(); // Create a URL object and open an InputStream A2ZXmlReader xmlreader = null; try { xmlreader = new A2ZXmlReader("http://itp.nyu.edu/icm/proxy/proxy.php?url=http://news.google.com/?output=rss"); // Call our recursive search function to locate the element we want ArrayList elements = new ArrayList(); xmlreader.fillArrayList(xmlreader.getRoot(),"title",elements); for (int i = 0; i < elements.size(); i++) { Element e = (Element) elements.get(i); // As long as we find the element if (e != null) { Node n = e.getFirstChild(); String headline = n.getNodeValue(); headline = headline.replaceAll("'","'"); if ((!headline.matches("Google News")) && (headlines.size() < maxheadlines)) { headlines.add(headline); } } } available = true; notifyAll(); // let's notify everyone that the headlines have been updated } catch (Exception e) { System.out.println("Something went wrong. " + e); } } |
Note also the use of synchronized keyword. This indicates that the thread should be locked down while this method is executed, i.e. other threads cannot have access to its internal data. We're also using notifyAll(), which alerts any threads that are waiting for data that it is ready. Now, whenever the updated ArrayList of headlines is retrieved by an external source, available is reset to false while we wait for the next reload time:
public synchronized ArrayList getHeadlines() { // We should put a while (!available) loop here // but since we are explicitly only calling this function if available is true, we're ok available = false; notifyAll(); // let's notify everyone that available has changed return headlines; } |
Finally, we include a method available() to return true or false based on whether or not new information has arrived:
public boolean available() { return available; } |
Our main program checks if new information is available, and acts accordingly. It never has to pause and wait for the data to be loaded since all that work is taken care of in the thread. We check every time through Processing's draw() loop.
void draw() { // If there is new news available, get it! if (news.available()) { headlines = news.getHeadlines(); } } |
Making your own Processing library
Looking closely at the above applets, you'll notice the following line of code:
import a2z.*; // Lookie, our code is a Processing library! |
Instead of having to include all of our java classes in a "code" folder for each sketch, or create each one as a separate .java tab, we can package up these classes into a JAR file and include it as a Processing library. Here are the steps:
It's also possible to write a library that registers itself with a parent applet and knows when certain events occur. We can also provide a Method instance (from: java.lang.reflect) that can be invoked in the parent applet when a given event occurs.
To implement these features, you'll want your class to contain a PApplet reference:
package mylib; import processing.core.*; public class MyLib { PApplet parent; public MyLib(PApplet p) { parent = p; parent.registerDraw(this); parent.registerDispose(this); } public void draw() { // Code here will be executed at the end of draw() in the parent applet } public void dispose() { // Code in here will be executed when the parent applet shuts down // (note: http://dev.processing.org/bugs/show_bug.cgi?id=183) } } |
Other methods you can register are: keyEvent, mouseEvent, pre, endFrame, stop, post. Full documentation is available in howto.txt (in the Processing libraries folder), and you may also find the forums helpful.
To create a callback method that the user writes in the main applet, create a Method instance in your library class:
Method eventMethod; |
Then, in the constructor, you can check and see if that method exists in the parent:
try { // Looking for a method called "myEvent", with one argument of PEvent type eventMethod = parent.getClass().getMethod("myEvent", new Class[] { PEvent.class }); } catch (Exception e) { System.out.println("Method not in parent class? " + e); } |
Later, whenever you feel like it, you can invoke that method:
// As long as the method exists if (eventMethod != null) { try { // Call the method with this object as the argument! eventMethod.invoke(parent, new Object[] {this} ); } catch (Exception e) { // Error handling System.err.println("I couldn't invoke that method for some reason."); e.printStackTrace(); eventMethod = null; } } |
Your processing applet would then include the method automatically called. Note this is exactly how serialEvent(), captureEvent(), etc. work!
import pevent.*; PEvent event; void setup() { event = new PEvent(this); } void myEvent(PEvent e) { println(e.read()); } void draw() { } |
Full source:
- Simple Processing Event library: pevent.jar, Library source: pevent.zip, Applet source: simple_eventlib.zip
- Processing NewsReader Event library: news.jar, Library source: news.zip, Applet source: news_event.zip