Search code examples
javamultithreadingrunnable

How to create n threads and work with all of them


Im trying to create a given number of threads and treat them at the same time to make a "race" program. The threads are created but im doing something wrong because any of the threads prints "Hi".

public class Principal implements Runnable{

    public static void main(String[] args) {

        int howManyThreads = 3;
        Thread thread[];

        thread = new Thread[howManyThreads];

        for ( int i=0; i < thread.length; i++ ){

            thread[i]= new Thread();
            thread[i].setName("Thread - " + i);
        }

        for ( int i=0; i < thread.length; ++i){

            thread[i].start();
            System.out.println(thread[i].getName() + " - " + thread[i].getState());
        }

    }

    public void run() {

        System.out.println("Hi");
    }
}

Solution

  • The default constructor for the Thread class creates a thread that does nothing. You're calling that default constructor here: thread[i] = new Thread();

    If you want the thread to actually do something, then you must provide a Runnable instance as an argument to the Thread constructor. There are a couple of ways to do that. The newest, most concise way is to use a lambda expression:

    thread[i] = new Thread(() -> {
        System.out.println("Hi");
    });
    

    The Runnable interface is an @FunctionalInterface. Since the compiler knows that the Thread(...) constructor wants an object of that type, it infers that that's what the lambda should create, and the body of the lambda becomes the run() method of the new object.


    Another, older way to provide a Runnable object is to use an anonymous inner class expression. The syntax is a little more cumbersome because you have to explicitly say what interface the new class should implement, and you have to explicitly declare the run() method:

    thread[i] = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Hi");
        }
    });
    

    The oldest way, still even more verbose, is to explicitly declare a named class:

    class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("Hi");
        }
    };
    
    public class Principal /*does not need to implement Runnable*/ {
        ...
        thread[i] = new Thread(new MyRunnable());
        ...
    }
    

    You might ask, why did I remove implements Runnable from the Principal class, and create a whole new class?

    I did it because, I've read this book: https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/