The simplest way to define concurrent threads in Java is to have a class extend the built-in class Thread. Suppose we have such a class, as follows, in which we define a function run() as shown:
public class Parallel extends Thread{ private int id; public Parallel(int i){ // Constructor id = i; } public void run(){ for (int j = 0; j < 100; j++){ System.out.println("My id is "+id); try{ sleep(1000); // Go to sleep for 1000 ms } catch(InterruptedException e){} } } }
Then, we can created objects of type Parallel and ``start'' them off in parallel, as follows:
public class TestParallel { public static void main(String[] args){ Parallel p[] = new Parallel[5]; for (int i = 0; i < 5; i++){ p[i] = new Parallel(i); p[i].start(); // Start off p[i].run() in concurrent thread } }
The call p[i].start() initiates the function p[i].run() in a separate thread. (Note that if we write p[i].run() instead of p[i].start() we just execute p[i].run() like any other function in the current thread--that is, control is transferred to p[i].run() and when it finishes, control passes back to the caller.)
Notice the function sleep(..) used in run(). This is a static function defined in Thread that puts the current thread to sleep for the number of milliseconds specified in its argument. Any thread can put itself to sleep, not just one that extends Thread. In general, one would have to write Thread.sleep(..) if the current class does not extend Thread. Observe that sleep(..) throws InterruptedException (like wait(), discussed earlier).
Of course, given the single inheritance mechanism of Java, we cannot always extend Thread directly. An alternative is to implement the interface Runnable. A class that implements Runnable is defined in the same way as one that extends Thread--we have to define a function public void run()... However, to invoke this in parallel, we have to explicitly create a Thread from the Runnable object by passing the reference to the object to the Thread constructor. Here is how we would rework the earlier example.
First the Runnable class:
public class Parallel implements Runnable{ // only this line // has changed private int id; public Parallel(int i){ ... } // Constructor public void run(){ ... } }
Then, the class that uses the Runnable class.
public class TestParallel { public static void main(String[] args){ Parallel p[] = new Parallel[5]; Thread t[] = new Thread[5]; for (int i = 0; i < 5; i++){ p[i] = new Parallel(i); t[i] = new Thread(p[i]); // Make a thread t[i] from p[i] t[i].start(); // Start off p[i].run() in concurrent thread // Note: t[i].start(), not p[i].start() } }
A thread can be in one of four states:
A Runnable thread need not be ``running''--it may be waiting to be scheduled. No guarantee is made about how scheduling is done but almost all Java implementations now use time-slicing across running threads.