Last week's example makes the basic principle behind using threads fairly clear:
...
class testThread extends java.lang.Thread {
...
run () {
/* This thread's instructions go here */
}
}
...
/* Back in the main() program: */
new testThread.start();
Place the code you want to run "in the background" in the run() method, and fire it off with the start() method. The Thread class takes care of the rest. This would suffice if, for some reason, it wasn't important that your thread share any information with the rest of your program while it was running, or share CPU time in any complex way with any of the other threads.
Most important to keep in mind is that threads, at any time, are still just objects; to use them, you have to treat them that way. To flesh out our previous example, let's clarify exactly what you'd need to do to create and start a thread in a real applet.
import java.applet.Applet;
import java.lang.Thread;
public class threadtest extends Applet {
public static double a = 100; // Define a public variable
mythread t1; // Define a thread variable
public void init () {
System.out.println("Starting..."); // Report our progress
t1 = new mythread(); // Instantiate our thread (NEW THREAD)
t1.start(); // Start the thread's execution (RUNNABLE)
do { // While loop:
System.out.println(a); // Print the value of a
} while (threadtest.a > 0); // Loop continues until a is zero
}
}
class mythread extends Thread {
public void run () { // Thread execution body starts here:
do { // Another loop:
System.out.println("Decrementing...");
threadtest.a--; // Decrement a by 1
} while (a > 0)
}
}
Note the way in which everything is distributed in the example. The applet class itself merely contains an arbitrary variable (a), and instantiates the thread "subclass" (class that inherits the traits of java.lang.Thread) we've defined later in the example. It then calls our thread's start() method, and continues doing its own thing, confident that the thread is doing its job.
Our thread definition merely consists of a class we've defined to "extend" Thread, with one method, run(). The contents of run, as we've said, will be executed independently of the rest of our program. Simultaneously, to be exact.
In this case, the applet itself is merely an endless loop once it kicks off the thread; the thread is an endless loop as well. If you "Show Java Console" in your Netscape "Options" menu, you'll see that this particular use of threads is extremely mundane; the thread counts down the variable and the applet continuously reports the thread's progress.
Threads have access to the same "variable space" that any other object would. Thus, your thread may reference a variable or method in another object (one marked public so that outside objects would have access to it), and vice versa. The simplest example of an application of this is one we've mentioned earlier; you can assign your thread the task of compiling some form of information (for instance, loading a sound or video file from over the network) and then go back about your business, confident (or hopeful, at least) that the thread has completed its work by the time you reference the variable within the thread that you need.
If you've got your Java console open, you'll notice that rather than seeing an orderly, alternating progression "Decrementing..." and a steadily decreasing number, you'll see something like this:
Decrementing... Decrementing... Decrementing... 50 47 47 47 47 47 47 Decrementing... Decrementing... Decrementing... 47 44 44 44
If you're wondering why the output isn't orderly, it's because threads are executed according to priority level. In fact, each thread has a numerical priority associated with it, and Java will, with refinements depending on where it's been implemented, give threads time to execute in order of priority. When two threads have the same priority, such as our applet and the thread it's created, then it executes both in an approximation of round-robin fashion.
Yes, you read correctly. As far as Java is concerned, your applet itself is a thread. As we hinted at earlier, the trick we're discussing here is how to actually create your thread so it makes other, additional threads.
How do we know that our applet and the thread we created to run with it have the same priority? It's a rule in Java that any thread defaults to the priority of the thread that instantiated it. How can we change the priority of a thread? Simple, just use setPriority().
Aside from just having your threads prioritized correctly, it's also good practice to use a method called yield() to indicate to the Java interpreter where it's convenient for your thread to "yield" its execution and allow other threads to execute.
Control is allowed "from the outside" over the execution of threads by way of straightforward methods like stop(), suspend(), and resume(). In case you're still not well adjusted to working with the object metaphor, these methods don't take your thread as a parameter, but are instead methods of the thread (t1.stop(), for instance).
A good example of when these methods come directly into play relates to our previous threadtest example. The actual applet running on your browser is not, exactly, made from the source shown earlier. There is an additional method defined in the threadtest applet class:
public void stop() {
t1.stop();
}
In fact, if this method were not in place, the thread that decrements a might continue to run at breakneck pace long after you've left this Web page and moved on to surf greener pastures elsewhere on the Internet. Remember, as we described weeks ago: The applet keeps running even after you leave the page, unless you tell it not to. (Of course, in this case, both loops conclude when a finally reaches zero, regardless.)
Come back again next Friday, when we plunge yet a little deeper into the threads under Java.
Past installments of Java Jolt