Threading

It is often the case that a computer program needs to do more than one thing simultaneously.  For example, a program might want to do some computation while waiting for user input.  If the user presses a key, the program should perhaps stop the other task it is performing and respond. 

A computer with a single CPU can run multiple programs simultaneously; for example, your computer might be playing audio in the background while you are actively inserting text into a Word document.  Your operating system has a scheduler that determines which program, or process, gets to run at any given time.  

Within a single process, threads are the programming abstraction that allow concurrent execution of several different tasks.  Your programs all have a main thread that begins executing when your program starts.  Your main thread may also spawn other threads that execute concurrently.  Again, you can conceptually think of the threads executing at the same time, but really a scheduler is deciding which thread gets to run at any given time.  As a result, you cannot guarantee how the individual statements in each thread are interleaved.

Java Threads

In Java, the typical approach to creating a thread is as follows:
  1. Create a class that implements the Runnable interface as shown the examples T1 and T2 below.
  2. An object of type Runnable must implement the method public void run().  Often, the body of this method contains a loop that executes repeatedly.  The example below uses while(true), which means that the loop will run forever.  A better approach is to use a boolean variable (for example, running) and continue to execute as long as the variable is true.  You can also provide a stop method in your Runnable class that changes the value of the variable to false and stops execution of the thread.
  3. To create a Runnable object and call its run method, you create a new object of type Thread.  The Thread constructor takes as input an object of type Runnable.  Once you have created the Thread object, you invoke the Runnable's run method by calling the start method on the Thread object.
public class T1 implements Runnable {

    public void run() {
        int count = 0;
        while(true) {
            System.out.println("T1 count: " + count++);
        }

    }

}

public class T2 implements Runnable {

    public void run() {
        int count = 0;
        while(true) {
            System.out.println("T2 count: " + count++);
        }       
    }

}

public class Threads1 {

    public static void main(String[] args) {
           
        Thread t1 = new Thread(new T1());
        t1.start();
       
        Thread t2 = new Thread(new T2());
        t2.start();

       
    }
   
}


The following example creates a Spinner object that will cycle through the numbers 0-5 until the user hits enter.  In order to count while listening for user input, the Spinner constructor creates a new thread that listens for user input.

This example also uses an anonymous inner class.  The Runnable object created in the constructor is specified in an unnamed class.   


import java.util.Scanner;

public class Spinner {

    private boolean spinning;
   
    public Spinner()
    {
        this.spinning = true;
       
        Thread t = new Thread()  {
            public void run() {
                Scanner s = new Scanner(System.in);
                String in = s.nextLine();
                spinning = false;   
            }
        };
        t.start();
    }
   
    public void spin() {
        int i = 0;
        while(spinning) {
            i = (i+1)%6;
            System.out.println("Number: " + (i+1));       
            try {
                Thread.sleep(100);
            } catch(InterruptedException ie) {
               
            }
        }
        System.out.println("Spinner::Final Number: " + (i+1));       
    }

    public static void main(String[] args) {
        (new Spinner()).spin();
       
    }
}


The next example implements the same functionality as the previous, but the main thread listens for input while the other thread cycles through the numbers.  This is a very common pattern for using threads.

import java.util.Scanner;

public class AnotherSpinner {


    class Wheel implements Runnable {
        private boolean spinning;
       
        public Wheel() {
            spinning = true;
        }

        public void run() {
            int i = 0;
            while(spinning) {
                i = (i+1)%6;
                System.out.println("Number: " + (i+1));       
                try {
                    Thread.sleep(100);
                } catch(InterruptedException ie) {
                   
                }
            }
            System.out.println("AnotherSpinner::Final Number: " + (i+1));
        }
       
        public void stop() {
            spinning = false;
        }
       
    }
   
   
    public void spin() {
        Wheel w = new Wheel();       
        Thread t = new Thread(w);
        t.start();
        Scanner s = new Scanner(System.in);
        s.nextLine();
        w.stop();
    }
   
   
    public static void main(String[] args) {
       
        AnotherSpinner as = new AnotherSpinner();
        as.spin();
    }
}


Comments