Java Tutorial 8: Starting Threads and Using Anonymous Classes

A thread is a separate process on your computer; you can run multiple threads all at the same time. The way the CPU (central processing unit) actually handles this is usually by switching rapidly between threads to give the illusion of multiple processes all happening simultaneously, although if you have more than one CPU, of course your computer can run code on both at the same time.

It is this feature of your computer that allows you to run multiple applications at the same time.

Multi-threaded code has the disadvantage of becoming quite complex very quickly, although Java has some great classes for dealing with multithreading and simplifying it.

The complexity arises when multiple threads need to access the same resources; having multiple threads modifying a single shared research (an array or whatever) is a potential recipe for disaster and needs to be handle carefully.

On the other hand you often absolutely need multiple threads -- for instance to monitor ports or message queues while at the same time running a user interface.

In this tutorial we'll just look at creating threads, along with using anonymous classes to simplify (or some would say, complexify) your code.

The Two Methods of Creating Threads in Java



There are two ways to create a thread in Java. The first way is to extend the Thread class, override the run() method with the code you want to execute, then create a new object from your class and call start().

The second method is to pass an implementation of the Runnable interface to the constructor of Thread, then call start().

We'll look at both of the methods in turn.

Extending the Thread Class



In the following code we've created a Worker class that extends Thread. We've overridden the run() method and put some code in it that simulates useful work. The code just loops repeatedly and outputs a method.

We've also used a static method of the Thread class, sleep(). You can pass sleep() a number of milliseconds to sleep for, and it pauses execution of the current thread for the amount of time you specify.


public class Worker extends Thread {

    @Override
    public void run() {
        
        // Loop for ten iterations.
        
        for(int i=0; i<10; i++) {
            System.out.println(i + " looping ...");
            
            // Sleep for a while
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // Interrupted exception will occur if
                // the Worker object's interrupt() method
                // is called. interrupt() is inherited
                // from the Thread class.
                break;
            }
        }
    }

}




Note that if we use sleep(), we have to catch InterruptedException. This exception is thrown if a thread is interrupted while it's sleeping. We can interrupt a thread by calling its interrupt() method. In our code here, we simply call break if the thread is interrupted. This keyword causes execution of any surrounding loop to cease.

In the code below, we create two Worker classes and call their inherited start() methods. Notice that they both run at the same time, not one after the other.


public class Application {

    
    public static void main(String[] args) {
        Worker worker1 = new Worker();
        worker1.start();
        
        Worker worker2 = new Worker();
        worker2.start();
        
        // You can call interrupt() if you want
        // to interrupt a thread. The thread itself
        // decides how to handle interrupts.
        // worker1.interrupt();
    }
    
}




0 looping ...
0 looping ...
1 looping ...
1 looping ...
2 looping ...
2 looping ...
3 looping ...
3 looping ...
4 looping ...
4 looping ...
5 looping ...
5 looping ...
6 looping ...
6 looping ...
7 looping ...
7 looping ...
8 looping ...
8 looping ...
9 looping ...
9 looping ...




The start() method, inherited from the parent Thread class, creates a new thread and runs whatever code is in run() in the new thread.

Of course, nothing stops us from calling the run() methods directly ourselves, but then the Worker.run() methods run one after the other, in the main program thread, not simultaneously.

How NOT to use threads:

public class Application {

    
    public static void main(String[] args) {


        Worker worker1 = new Worker();
        worker1.run();
        
        Worker worker2 = new Worker();
        worker2.run();
        
        // You can call interrupt() if you want
        // to interrupt a thread. The thread itself
        // decides how to handle interrupts.
        // worker1.interrupt();
    }
    
}




0 looping ...
1 looping ...
2 looping ...
3 looping ...
4 looping ...
5 looping ...
6 looping ...
7 looping ...
8 looping ...
9 looping ...
0 looping ...
1 looping ...
2 looping ...
3 looping ...
4 looping ...
5 looping ...
6 looping ...
7 looping ...
8 looping ...
9 looping ...




... and of course this code, which doesn't use multithreading, takes twice as long to run.

Passing Code to Thread Directly



The second method of starting a thread is to put the code you want to run in the run method of a class that implements the Runnable interface, then pass it to the constructor of a Thread class.

The code below does exactly that; we've put the code all in one file to make it easier to follow.


class CodeRunner implements Runnable {

    @Override
    public void run() {
        // Loop for ten iterations.
        
        for(int i=0; i<10; i++) {
            System.out.println(i + " looping ...");
            
            // Sleep for a while
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                break;
            }
        }       
    }
    
}

public class Application {

    
    public static void main(String[] args) {
        
        CodeRunner runner = new CodeRunner();
        
        Thread thread = new Thread(runner);
        thread.start();
    }
    
}





0 looping ...
1 looping ...
2 looping ...
3 looping ...
4 looping ...
5 looping ...
6 looping ...
7 looping ...
8 looping ...
9 looping ...




Once again the code is running in its own thread, and we could run more or less as many instances of CodeRunner as we like simultaneously, within reason.

We can simplify this code by calling new directly on our CodeRunner class, right where we create the Thread.

Thread thread = new Thread(new CodeRunner());
thread.start();




Quick and Dirty Threads Using Anonymous Classes



In fact we can make this code even terser by creating a new instance of Runnable, sort of, directly in the Thread constructor.

Actually, we can't create a new instance of Runnable because it's an interface; so we can't do the following:

// Won't work
Thread thread = new Thread(new Runnable());
thread.start();




But we can get this to work if we add in some curly brackets and implement the missing run() method in them.

// This works
Thread thread = new Thread(new Runnable() {

    @Override
    public void run() {
                
    }
            
});
        
thread.start();




Pretty crazy eh? What is the class of the object that we've passed to Thread() exactly? It's not an instance of Runnable; Runnable is just an interface. It's an instance of a class that has no name -- an anonymous class -- that implements Runnable.

You can actually use the same trick with abstract classes, and you can also override methods of existing classes in the same way.

This technique, while odd-looking, is often used in Java; for instance not only to create threads, but in implementing the actions associated with buttons in Swing.

Of course, to get this code to do anything, we have to add some actual code to run.

Thread thread = new Thread(new Runnable() {

    @Override
    public void run() {
        for(int i=0; i<10; i++) {
            System.out.println(i + " looping ...");
        }   
    }
    
});

thread.start();




0 looping ...
1 looping ...
2 looping ...
3 looping ...
4 looping ...
5 looping ...
6 looping ...
7 looping ...
8 looping ...
9 looping ...




Finally, we can make the code even more terse, if a little more cryptic, by not bothering to declare a variable to hold the Thread class, and then just calling the start() method on it directly.

new Thread(new Runnable() {

    @Override
    public void run() {
        for(int i=0; i<10; i++) {
            System.out.println(i + " looping ...");
        }   
    }
    
}).start();






(I've removed the sleep() here just to make the code a bit clearer. You probably wouldn't want to put huge amounts of code into a method or constructor call like this, but it's often handy when you just need to invoke one or two methods).