2

I am trying to create a new thread with an custom object, and then call this custom objects method from the main thread. The idea is that the main thread can go on doing other stuff, while the custom object goes on working in the second thread:

public class Multithreading {
    public static void main(String[] args) {

        Multithreading mt = new Multithreading();
        mt.multiTest();
    }

    public void multiTest() {
        SomeObject someObject = new SomeObject();
        Thread thread = new Thread(someObject);
        thread.setDaemon(true);
        thread.start();
        someObject.startit();
        int i = 0;
        while (i < 3) { 
            try {

                System.out.println("this is the main thread being busy");

                Thread.sleep(3000);
                i += 1;
            } catch (InterruptedException e) {
            }

        }
    }

    class SomeObject implements Runnable {

        public void sayHello() {
            System.out.println("this is the second thread being busy");
        }

        public void startit() {
            int i = 0;
            while (i < 3) {
                try {
                    sayHello();

                    Thread.sleep(3000);
                    i += 1;
                } catch (InterruptedException e) {
                }
            }

        }

        @Override
        public void run() {
            // TODO Auto-generated method stub

        }
    }
}

The output is:

this is the second thread being busy
this is the second thread being busy
this is the second thread being busy
this is the main thread being busy
this is the main thread being busy
this is the main thread being busy

It should be more like this:

this is the second thread being busy
this is the main thread being busy
this is the second thread being busy
this is the main thread being busy
this is the second thread being busy
this is the main thread being busy

So the main Thread is blocked until the method is completed. Is the main thread waiting for completion of someObject.startit() in the second thread(Being void as return type, I would think that this would not be the case)? Or is it executed in the first thread, therefore blocking it?

I know that with the following code I could execute someObject.startit() in another thread, but it would be created from scratch every time, and I cant afford the thread creation overhead:

new Thread(() -> {someObject.startit();}).start(); 

How can one thread call methods from an object in another thread without blocking?

harbun
  • 515
  • 6
  • 23
  • Every time you need to run a separate thread, you need to create a new thread object. There is no way to avoid that overhead. You can't reuse a thread object. Most importantly, you seem to have a misconception, that once you put an object in a thread and start the thread, any operation in that object is run by that thread. That's not true. – RealSkeptic Apr 25 '18 at 14:40
  • related: https://stackoverflow.com/questions/13327571/in-a-simple-to-understand-explanation-what-is-runnable-in-java – Mark Rotteveel Apr 25 '18 at 14:40

5 Answers5

2

What is executed in another is the run method of a Runnable object. In your case the run method is empty, so nothing is done in the other thread. Then you call startit() but from the main thread, so it's executed in the main thread. This is why you get this result.

Try putting the body of startit() inside run

vincrichaud
  • 2,218
  • 17
  • 34
2

Is the main thread waiting for completion of someObject.startit() in the second thread(Being void as return type, I would think that this would not be the case)? Or is it executed in the first thread, therefore blocking it?

When you call someObject.startit() directly in multiTest, it is executed in the first calling thread.

It is very important to understant that Runnbale is not Thread, Runnbale is just normal object, except its run method will be executed when you create and start a new Thread with it, like this:

new Thread(new Runnable()).start;

So, actually, there is nothing to do with thread blocking in this case. You can move startit() to the run method, so it will be executed by the second thread:

@Override
public void run() {
    startit();
}

And, to avoid thread creation overhead, you can use a thread pool to execute it:

ExecutorService executorService = Executors.newCachedThreadPool(); // It should a singlton
// ExecutorService executorService = Executors.newFixedThreadPool(threadSize);
executorService.execute(() -> {
    someObject.startit();
});
xingbin
  • 27,410
  • 9
  • 53
  • 103
  • I see. Makes sense that it is running in the main thread because that thread called it. Problem with `run()` is, I want to execute different methods from an object, depending on which one I need at the moment, in another thread. With `run()` this is not possible, because the methods are hardcoded into the object and the same every time. – harbun Apr 25 '18 at 15:12
  • @harbun If you want to avoid thread creation overhead, you can use a thread pool. See my update. – xingbin Apr 25 '18 at 15:20
0

someObject.startit(); is running sequentially and not running on the thread you created.

to make it work you need to call startit(); method in your run() method of SomeObject class

nafas
  • 5,283
  • 3
  • 29
  • 57
0

You should call your function in run method, because it is the method which actually achieve the multithreading.

0

If I understand you correctly you want to create a new thread and then order that thread to do some calculations without creating a new thread every time.

I would suggest that you use the ExecutorService class. It can be used to manage a group of threads that will accept new concurrent work without the overhead of creating a new Thread every time a method should be called.

Initalize the service with:

 ExecutorService pool = Executors.newFixedThreadPool(poolSize);

Then to run a method in one of the threads in the pool call pool.execute(Runnable). In this example I will use your startit method on someobject. If there is a thread available in the pool it will be run in that thread, otherwise it will be put on a queue to wait for a thread to become available.

 pool.execute(someObject::startit);
Diasiare
  • 745
  • 1
  • 6
  • 18