1

I'm writing a Java application that uses some threads. Main method looks like this:

WorkerThread[] thread = new WorkerThread();
for (int i = 0 ; i<10 ; i++) {
    thread = new WorkerThread();
    thread.doStuff();
}

and my WorkerThread looks like this:

class WorkerThread {
    public void run() {
        ...
    }

    public void doStuff() {
        ...
    }
}

The matter is that, obviousely, I call doStuff from the run method it is executed like concurrently with other threads, but if i call doStuff directly from the main it is executid not cocurrently.

Ok, now the question is: is there a way to execute, concurrently, the doStuff method calling it not from the run method, but rather, from the main?

8
  • 3
    There is, creating anonymous Runnables inside main, but why? Commented Dec 2, 2012 at 16:28
  • 1
    I'm guessing his run method has logic he doesn't want to execute in all cases. Commented Dec 2, 2012 at 16:29
  • 3
    I would strongly urge you to check out the classes in the concurrent package, not write raw Threads, and read "Concurrency in Java" Commented Dec 2, 2012 at 16:30
  • 1
    Not to put too fine a point on it, but you need to learn more about writing multi-threaded code in Java so that you understand the basic concepts before attempting whatever it is you're attempting. Commented Dec 2, 2012 at 16:37
  • 1
    @BenBrunk if you give me a tip I can understand, but if you don't do that how can you help me? Commented Dec 2, 2012 at 16:39

4 Answers 4

2

You cannot directly call methods on a Thread object. The only way to get concurrency with a Thread is to invoke its start() method, which in turn calls run() on a separate thread of execution. Calling any other methods directly from main() is just like calling methods on regular non-Thread objects; there's no concurrency, nothing special happens, the methods execute immediately.

It sounds like you're trying to communicate between the main thread and the worker threads. Each thread's run() method is in charge of executing code on that thread. If you can communicate with that run() method then you can control what happens on that thread.

One way to do that is to pass a variable in when you construct the Thread. Save a value that the run() method can examine to determine what to do. For example, below we have an enum that has three possible actions in it. The run() method looks at the enum and decides what to do based on the value that was passed to the WorkerThread() constructor.

class WorkerThread {
    public enum Action { DO_STUFF, MAKE_WIDGETS, FROB_BARS }
    private Action action;

    public WorkerThread(Action action) {
        this.action = action;
    }

    public void run (){
        switch (action) {
            case DO_STUFF:     doStuff();     break;
            case MAKE_WIDGETS: makeWidgets(); break;
            case FROB_BARS:    frobBars();    break;
        }
    }

    public void doStuff()     { ... }
    public void makeWidgets() { ... }
    public void frobBars()    { ... }
}

Now our main() method looks like this. You create WorkerThreads passing in the action to perform, then call start().

WorkerThread[] threads = new WorkerThread[10];
for (int i = 0; i < threads.length; ++i) {
    threads[i] = new WorkerThread(WorkerThread.Action.DO_STUFF);
    threads[i].start();
}

You could do the same thing in myriad different ways. Instead of having one WorkerThread class you could have several different classes with differing run() methods and then instantiate the appropriate sub-class from main().

class DoStuffWorkerThread     extends Thread { ... }
class MakeWidgetsWorkerThread extends Thread { ... }
class FrobBarsWorkerThread    extends Thread { ... }

You can even create anonymous Thread classes right inside main(), if you like. Then the logic can be whatever main() wants.

Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; ++i) {
    threads[i] = new Thread() {
        public void run() {
            doStuff();
        }
    };

    threads[i].start();
}
Sign up to request clarification or add additional context in comments.

3 Comments

Perfect, I had not thought to this implementation. Great :-)
I don't think it's a good way to handle different jobs in a switch case?
If your code grows, it becomes difficult to maintain it. With separate Runnable's or classe's, it is easier to expand the functionality later.
0

When you are using thread.doStuff(); you are not using Threading, as to use threading you will have to call thread.start() method, which will internally call run() method internally.

1 Comment

What I need is to call the right method at runtime: I don't have some code to be executed always. I have to be able to choose the right method from the main
0
 Thread[] threads = new Thread()[10];
    for (int i = 0 ; i<10 ; i++) {
        if ( i<5) {
          threads[i] = new Thread(new WorkerA());
        } else {
          threads[i] = new Thread(new WorkerB());
        }
        threads[i].start();
    }

At first, you're creating an array but don't use it right. You can not assign a Object to an array? Then you have to call the start() method to execute the thread in background and invoke his run method.

Your Worker's should look like this:

class WorkerA implements Runnable {            

    public void run (){
        ...
        // put here your code from doStuff in one Version
        ...
    }

}

class WorkerB implements Runnable {

    public void run (){
        ...
        // put here your code from doStuff in an other Version
        ...
    }

}

Instead of calling the thread[i].start() in your loop, you can now call it anywhere with the reference to your array.

3 Comments

ok but in this way I cannot choose the method of WorkerThread to call at runtime!
perhaps I should extend an abstract class that implements runnable and call run on it
if you think you need nearly the same routines and fields in each class, but in some different ways to be executed, than yes, extending an abstract class should do the job. Apart you should create your own class implementing the Runnable interface.
0

You can use Runnable for that.

// Dictate what work needs to be done
Runnable work = new Work(); // or new OtherWork();

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

class Work implements Runnable {
    public void run(){
        System.out.println("do stuff");
    }
}

class OtherWork implements Runnable {
    public void run() {
        System.out.println(" do other stuff");
    }
}

EDIT:
It is recommendable to use thread pools instead of creating (and discarding) threads for each task. This is because there is some overhead in creating/discarding threads, and it also makes it easier to manage at what concurrency the tasks should be done etc.

Anyways, you could create your thread pool by yourself using Thread class, but that's a lot of work and it's hard to get it right. Instead, it's best to use the ready made solution available in the JDK. You can use it as follows:

ExecutorService threadPool = Executors.newFixedThreadPool(4);
threadPool.execute(new Work());
threadPool.execute(new OtherWork());

// After submitting all your task (or when your application wants to terminate)
// You should call shutdown() on the thread pool so that the JVM can exit
threadPool.shutdown();

3 Comments

So, in your opinion, I should create some Threads that do specific jobs and just run theme.
@litiales: Well the recommended way is to use thread pools. Creating a thread for each specific jobs will work too though. It's just not efficient.
I've already created a FixedThreadPool! But how can it help me?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.