3

I am new to multi threading and while practising I wrote the following code. I want to call the createThred method to create a new thread evrytime I call it. However, With the below given code, everytime the createThread method is called, i get the same thread running again and again. Is it possible to create a new thread using the same object? Appararently not but just wanted to confirm if there is a way I dont know of.

public class ThreadStartRunnable implements Runnable {

    private Thread t;
    /*
     ThreadStartRunnable(String name) {
         t = new Thread(this, name);
        t.start();
        }
     */
       private Thread createThread(String name){

         t = new Thread(this,name);
         t.start();
         return t;
     }

    /**
     * @Override run
     * 
     */
    public void run() {

        for(int i=0;i<=5;i++)
        {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("The current Thread is " + t.getName() + " and thread ID is " + t.getId());
        }
    }
    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args)  {
        // TODO Auto-generated method stub

        Thread t = Thread.currentThread();
        //new ThreadStartRunnable("User 1");
        //new ThreadStartRunnable("User 2");
        //ThreadStartRunnable c = new ThreadStartRunnable();
        ThreadStartRunnable t1 = new ThreadStartRunnable();

        t1.createThread("Child 1");
        t1.createThread("Child 2");

        for(int i=0;i<=5;i++)
        {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("The cirrent Thread is " + t.getName()+ " and thread ID is " + t.getId());
        }




    }

}

OUTPUT:

The current Thread is Child 2 and thread ID is 9

The current Thread is Child 2 and thread ID is 9

The cirrent Thread is main and thread ID is 1

The current Thread is Child 2 and thread ID is 9

The current Thread is Child 2 and thread ID is 9

The current Thread is Child 2 and thread ID is 9

The current Thread is Child 2 and thread ID is 9

The current Thread is Child 2 and thread ID is 9

The current Thread is Child 2 and thread ID is 9

The cirrent Thread is main and thread ID is 1

The current Thread is Child 2 and thread ID is 9

The current Thread is Child 2 and thread ID is 9

The current Thread is Child 2 and thread ID is 9

The current Thread is Child 2 and thread ID is 9

The cirrent Thread is main and thread ID is 1

The cirrent Thread is main and thread ID is 1

The cirrent Thread is main and thread ID is 1

The cirrent Thread is main and thread ID is 1

Sameer
  • 757
  • 1
  • 14
  • 35
  • your code is working for me. Try creating 5 different threads – washcloth Apr 17 '14 at 14:07
  • You are losing your reference to "Child 1" thread. You want to make multiple instances of `ThreadStartRunnable` or, change your code to have multiple `Thread`s within a single instance of `ThreadStartRunnable`. – wns349 Apr 17 '14 at 14:10
  • @ExcelledProducts No its is not. I runs five times but look atthe name and the ID for the child threads. – Sameer Apr 17 '14 at 14:11
  • @wns349 t = new Thread(this,name); show take care of the later but it is not. I do not want to create multiple instances of ThreadStartRunnable – Sameer Apr 17 '14 at 14:13
  • This doesn't really answer your question, but if you want to perform multithreaded tasks, you should look into the Executors and ExecutorService provided by java.util.concurrent package. – jgitter Apr 17 '14 at 14:15
  • never run the same instance of Runnable object on different threads. – Alexei Kaigorodov Apr 17 '14 at 14:18
  • @AlexeiKaigorodov Does this code actually create 2 threads but looses reference to the first one or not. If it were the former case, it still would have printed both the threads as the start method got called? – Sameer Apr 17 '14 at 14:22
  • @shawn It is losing the reference to the first thread (Child 1). It's printing Child 2 on console since `t` variable is pointing at the second thread (Child 2). `t` is being shared between the Child 1 and Child 2. Not a good design for your requirement. – wns349 Apr 17 '14 at 14:24
  • @AlexeiKaigorodov not true. this should work: see http://stackoverflow.com/questions/9562505/initializing-two-threads-with-the-same-instance-of-a-runnable – RokL Apr 17 '14 at 14:25
  • @UMad Thanks for the answer, I had one more basic question, can we make the thread t; statement as static and can we make the createThread statement as static as well, when I tried doing this, the run method did not execute on calling the start method. – Sameer Apr 17 '14 at 14:41
  • @U Mad that example work because it does not work with fields. – Alexei Kaigorodov Apr 17 '14 at 15:17

4 Answers4

3

The reason why it always says Child 2 is because you are printing the name of the Thread t member, which is the last thread created.

Replace:

System.out.println("The current Thread is " + t.getName() + " and thread ID is " + t.getId());

with

System.out.println("The current Thread is " + Thread.currentThread().getName() + " and thread ID is " + Thread.currentThread().getId());

Otherwise it's fine to use same runnable: Initializing two threads with the same instance of a runnable

Community
  • 1
  • 1
RokL
  • 2,663
  • 3
  • 22
  • 26
2

Change you code in run method to display name of the current thread instead:

System.out.println("The current Thread is " + Thread.currentThread().getName() + " and thread ID is " + Thread.currentThread().getId());

Every time you create new Thread you override instance variable t, so it is not safe to use it to track thread name and ID.

hoaz
  • 9,883
  • 4
  • 42
  • 53
  • I had one more basic question, can we make the thread t; statement as static and can we make the createThread statement as static as well, when I tried doing this, the run method did not execute on calling the start method. – Sameer Apr 17 '14 at 14:41
  • 1
    Yes, this is possible. You then also need to change thread initialization to something like this: `t = new Thread(new ThreadStartRunnable(),name);`. Also I do not really understand why do you need variable `t`? You can make it local – hoaz Apr 17 '14 at 14:54
1

You might want to use ExecutorService to run multiple threads within a single object.

Look at the code below:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test1 {
    private ExecutorService threads;

    public Test1(int poolSize) {
        // Use fixed-size thread pool
        threads = Executors.newFixedThreadPool(poolSize);
    }

    public void createThread(String name) {
        threads.execute(new MyThread(name)); // Create MyThread
    }

    public class MyThread extends Thread {
        // Constructor passing thread name
        public MyThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            for (int i = 0; i <= 5; i++) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("The current Thread is " + super.getName()
                        + " and thread ID is " + super.getId());
            }
        }
    }

    public static void main(String[] args) {
        Thread t = Thread.currentThread();
        Test1 t1 = new Test1(3);

        t1.createThread("Child 1");
        t1.createThread("Child 2");

        for (int i = 0; i <= 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("The cirrent Thread is " + t.getName()
                    + " and thread ID is " + t.getId());
        }
    }
}
wns349
  • 1,266
  • 1
  • 10
  • 20
1

The problem is you're using a single reference, this.t, to store the thread, then when you create the second thread you overwrite that single reference so that it now points to that second thread. So of course when you print t.getName() it is going to refer to the 2nd thread.

If you want your code to behave as expected, print the current thread, not t, like this:

System.out.println("The current Thread is " + Thread.currentThread().getName() + " and thread ID is " + Thread.currentThread().getId());
Magnus
  • 10,736
  • 5
  • 44
  • 57