A SIMPLE JAVA THREADS EXAMPLE



In this section of the tutorial, we are going the play with threads. The first example that we will be examining is called thread_ex.java. In this example, we will spawn three threads:


The counter threads are threads that simply count from 1 to 50. The update thread is a thread that will handle updating the display. We will have two numbers display and two buttons displayed (one for each counter thread). If the user clicks on a button, that corresponding thread will run incrementing the count. If the user clicks on that same button again, the counting will stop and that thread will be suspended. The button is a toggle switch for the thread to run or not run. After a count of 50 for each counter has been reached, the application is done.

THE thread_ex APPLET

Counter class source
thread_ex class source

Please get a Java compatible browser

THE COUNTER CLASS


1:  class Counter extends Thread {
2:  /* This class simply runs a thread to count to 50 */
3:     public int count = 1;
4:
5:      public void run() {
6:          while (count < 50) {
7:              try {
8:                  sleep(1000);
9:              } catch (InterruptedException e) { }
10:            count++;
11:        }
12:			stop();
13:    }    
14: }

As you can see this class is very simple. If you first look at Line 1, you will notice that the Counter class inherits from the Thread class. Since it inherits from a Thread, the only method that needs to be created is the run() method. Line 6 says to keep running while the count is less than or equal to 50. Line 7 is the form of exception handling used in Java. Since the sleep() method throws an InterruptedException, this exception must be caught whenever the sleep() method is applied. To catch the exception the try{} catch () {} clause should be used. Line 8 will cause the thread to sleep for the specified number of milliseconds. Sleeping causes the currently executing thread to temporarily cease execution for the specified amount of time. The thread does not lose ownership of any monitors. Line 10 increments the count by one. Finally, line 12 calls the stop() method to stop the thread from running once it has reached 50.

THE thread_ex CLASS

THE CLASS AND INSTANCE VARIABLES



1: public class thread_ex extends java.applet.Applet implements Runnable {
2:  /* APPLET */
3:    final static int NUMCOUNTERS = 2;
4:    final static int SPACING = 23;
5:
6:    Counter[] counters = new Counter[NUMCOUNTERS];
7:    Thread updateThread = null;
8:
9:    boolean[] clicked = new boolean[NUMCOUNTERS];

Line 1 inherits from the Applet class like the previous examples, but it also implements the Runnable interface. This interface is the interface that allows the user to use threads. Line 3 declares an int called NUMCOUNTERS which is declared a class variable by the modifier static. It is also declared to be unchangeable (a constant) by the modifier final. NUMCOUNTERS is the number of instances of the Counter class. Line 4 handles the spacing between the two threads displayed. Line 6 declares an array of counters, while line 7 declares a Thread called the updateThread to be initially null. The updateThread will be the thread used to handle the applet events.

init() method


1: public void init() { 2: /* Make new counters */ 3: for (int i = 0; i < NUMCOUNTERS; i++) { 4: counters[i] = new Counter(); 5: counters[i].setPriority(2); 6: clicked[i] = false; 7: } 8: 9: /* Make updateThread for drawing */ 10: if (updateThread == null ) { 11: updateThread = new Thread(this, "Count Program"); 12: updateThread.setPriority(NUMCOUNTERS+2); 13: } 14: 15: /* Make on/off buttons for threads */ 16: for (int i = 0; i< NUMCOUNTERS; i++) { 17: add(new Button(("ON/OFF " + i))); 18: 19: } 20: }
Line 5 sets the individual counters thread priority to 2. Line 10 checks to see if the updateThread has been created already. If it has not, then a new thread is created with the call in Line 11. The first parameter is the Runnable target, and the second parameter is the name you want to associate with the thread. Line 12 sets the priority for the updateThread to NUMCOUNTERS+2 (in this case 4), which is greater than the counters thread. This greater priority means that the updateThread will be scheduled for execution before the counters threads.

check_button METHOD


1:    void check_button(String bname) {
2:    
3:         // Start updateThread
4:         if (!updateThread.isAlive())
5:             updateThread.start();
6:  
7:         for (int i = 0; i < NUMCOUNTERS; i++) {
8:            if (bname.equals("ON/OFF " + i)) {
9:                 // Start that buttons thread
10:                if (!counters[i].isAlive())
11:                {
12:                    // Never started so start it
13:                    counters[i].start();
14:                }
15:                else if (clicked[i] == false) {
16:                    // Button hit so resume
17:                    counters[i].resume();
18:                }
19:                else if (clicked[i] == true) {
20:                    // Button hit so turn off
21:                    counters[i].suspend();
22:                }
23:                clicked[i] = !clicked[i];  // Say button was hit
24:            }
25:        }
26:    }

Line 4 uses the isAlive() method call to test if the updateThread has started. If it has not, it is started by using the start() method. The start() method will call the run() method defined for that thread along with setting up some other information. Line 13 runs the counters start() method if the counters thread is not alive. Else if the button was clicked upon resume the suspended thread as stated in lines 15-18. Lines 19-22 will suspend the running counters thread.

run() METHOD


    public void run() {

        while (updateThread == Thread.currentThread()) {
        // Repaint until count > 50
            for (int i = 0; i < NUMCOUNTERS; i++) {
                if (counters[i].count <= 50)
                {
                    repaint();
                    try {
                        updateThread.sleep(1000);
                    } catch (InterruptedException e) {}
                }  
                else counters[i].stop();
            }   
            for (int i = 0; i < NUMCOUNTERS; i++) {
                if (counters[i] != null)
                    if (counters[i].count > 50) stop();
            }
        }
    }


The run() method is the method invoked whenever the start() is applied to a thread. All the run() method does in this example is handle the repainting of the applet. It sleeps for every 1000 milliseconds to give the counters threads a chance to run. Then when both counters have reached 50 the threads are stopped.

stop() METHOD


    public void stop() {
    // Stops all threads
        for (int i = 0; i< NUMCOUNTERS; i++) {
            if (counters[i].isAlive()) {
                counters[i] = null;
            }
        }
        if (updateThread.isAlive()) {
            updateThread = null;
        }
    }

This method simply will stop all the running threads. If the user decides to hit the Back button on the browser, you most likely do not want the threads to still be running. The stop() method does this procedure by setting the threads to null if they are still alive. The stop() method is invoked whenever the applet is scrolled out of view, or the page the applet is no longer being looked at.