1

Assuming I have a class extending Thread.

So from what I know so far:

  • the run() method is treated just like an ordinary method when being called directly and it will not cause the JVM to create a new thread for it.

  • in order to have it work as intended, the start() method must be called, which, in turn, calls the run() method, after some OS dark juju magic takes place.

My question is:

Is there any way someone can overload start()/run() and keep the normal behaviour?

Note: you are mistaking curiosity for stupidity, no need to be rude.

Gray
  • 115,027
  • 24
  • 293
  • 354
CosminO
  • 5,018
  • 6
  • 28
  • 50

6 Answers6

5

You could do this if you subsclass Thread, by calling Thread's start or run method, respectively. However, if you intend to pass parameters to the underlying code, I suggest you to implement a Runnable instead and keep the parameters in its state:

class MyRunnable implements Runnable {

    private final int a;
    private final int b;

    public MyRunnable(int a, int b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public void run() {
        // do something with a and b
    }   
}

a and b are sort of "parameters in this sample. You can pass an instance to a Thread in its constructor, and then just start it. By the way this is sort of an implementation of the Command Pattern.

Matthias Meid
  • 12,455
  • 7
  • 45
  • 79
  • 3
    +1. also makes you more flexible in that you don't have to use Thread at all, you can use Executors. – Thilo Sep 27 '12 at 08:31
3

Of course:

class StupidThread extends Thread {
    @Override
    public void start() {
        run();
    }
}

But why would you do this? You cannot do this globally for every thread created in JVM, you are however free to use StupidThread wherever you want.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
3

You can override start/run methods in Thread because start and run methods in Thread class are not final methods. Ex : isAlive(), stop(), suspend(), join() are final methods. So U can't override.

public class TempThread extends Thread
{
    @Override
    public synchronized void start() {
        // TODO Auto-generated method stub
        super.start();
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
    }       

    public static void main(String[] args) 
    {
        TempThread t = new TempThread();
        t.start();
        t.run();
    }
}

But as you asked about Overload

You can overload any of these methods.

Ex :

public class TempThread extends Thread
{
    @Override
    public synchronized void start() {
        // TODO Auto-generated method stub
        super.start();
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
    }

    // ******** Overload **********
    public synchronized void start(int i) {
        // TODO Auto-generated method stub
        super.start();
    }

    // ********* Overload **********
    public void run(int i) {
        // TODO Auto-generated method stub
        super.run();
    }

    public static void main(String[] args) 
    {
        TempThread t = new TempThread();
        t.start();
        t.run();
    }   
}

Note : Check the differences between overriding and overloading. That gives you better understanding about the issue.

Munesh
  • 1,509
  • 3
  • 20
  • 46
  • I know the difference, I asked about overloading, not overriding. The answer you provided is answering my question, as I could call something like start(parameter), then before super.start(), I could set the parameter. Thank you. – CosminO Sep 27 '12 at 09:43
  • @Munesh `t.run()` will be part of `TempThread` or `MainThread` ? mean which thread will execute `t.run()`? – Asif Mushtaq Mar 06 '16 at 14:12
  • @UnKnown : t.run() will execute the run() method of TempThread. t.start() will execute the TempThread. When we run the Java program it will automatically start the main thread and any thread you invoke(t.start()) will be invoked from main thread. – Munesh Mar 06 '16 at 15:34
2

If you want to use an overload of the run() method you'll have to do this from the body of the run() method. Of course if you're doing that, you might as well not call the method run().

As for overloading the start() method. It could be thought of as a JNI method that calls pthread_create() or similar and then calls your run() method. In reality it's probably implemented differently for performance reasons. You're best not meddling with it. You could however consider overloading the thread constructor as is shown in the first example on this page: http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html.

 class PrimeThread extends Thread {
     long minPrime;
     PrimeThread(long minPrime) {
         this.minPrime = minPrime;
     }

     public void run() {
         // compute primes larger than minPrime
          . . .
     }
 }
Will
  • 4,585
  • 1
  • 26
  • 48
2

One alternative is to create an anonymous instance of Runnable. This will allow you access final local variables and final parameters (of the method that creates the Runnable) and the fields of class that creates the Runnable. Additionally, you also get access to the methods of the enclosing class.

eg.

class SomeClass {

    // constructor, getter and setter not included for brevity

    private String field;

    public void startNewThread(final String parameter) {
        final double local = Math.random();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(field + parameter + local);
            }
        }).start();
    }
}

WARNING: As the enclosing class may be modified by another Thread so directly accessing non-final fields is discouraged as you make get an out of date value. Either make access by a synchronised getter or only access final fields (whose contents are immutable if objects).

Dunes
  • 37,291
  • 7
  • 81
  • 97
0

I found that the method given above based on calling super.start() didn't parallelize as expected. One workaround to this is to pass your arguments as member variables to a subclass of thread:

public class MyRunnable extends Thread {
    private int id=0;
    MyRunnable(int i){
    this.id=i;
}


public void run() {
    System.out.println("Starting run: " + (id+1));
    try {
        TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("Finishing run: " + (id+1));
}

public static void main(String args[]) {
    MyRunnable threadArray[] = new MyRunnable[5];
    for (int j = 0; j < 5; j++) {
        threadArray[j] = new MyRunnable(j);
        threadArray[j].start();
    }
}


}

Obviously I've used a constructor here, but you could use a setter method before calling the run() method.

rwold
  • 2,216
  • 1
  • 14
  • 22