OVERTONE
OVERTONE

Reputation: 12187

Good thread design: "Method in Thread" or "Thread in Method"

This is just a general question on actual thread design. I'm using Java on android specifically but general design would be the better focus of this question.

Its simple enough, which is better method in thread or thread in method.

Example,

Lets say we have 3 methods/functions/whatever.

public void readMail()
{
    //Logic...
}
public void postQuestion()
{
    //Logic...
}
public void answerQuestion()
{
    //Logic...
}

Is it better to have


A: Thread within Method

public void readMail()
{
    new Thread(new Runnable()
    {
        public void run()
        {
            //Logic
        }
    }).start();
}

And then call your method as you normally would in any OO situation. Say

Email.readMail();

B: Method within Thread

//note this could be inside a method or a class that extends runnable
new Thread(new Runnable()
{
    public void run()
    {
        readMail();
        postQuestion();
        answerQuestion();
    }
}).start();

Upvotes: 4

Views: 258

Answers (5)

OldCurmudgeon
OldCurmudgeon

Reputation: 65811

I prefer:


C: One Thread One Object

public class Test {
  public static class MailReader implements Runnable {
    public void readMail() {
      //Logic...
    }
    @Override
    public void run() {
      while (!Thread.currentThread().isInterrupted()) {
        readMail();
      }
    }
  }

  public static class QuestionPoster implements Runnable {
    public void postQuestion() {
      //Logic...
    }
    @Override
    public void run() {
      while (!Thread.currentThread().isInterrupted()) {
        postQuestion();
      }
    }
  }

  public static class QuestionAnswerer implements Runnable {
    public void answerQuestion() {
      //Logic...
    }
    @Override
    public void run() {
      while (!Thread.currentThread().isInterrupted()) {
        answerQuestion();
      }
    }
  }
  public static void main(String[] args) throws FileNotFoundException {
    new Thread(new QuestionAnswerer()).start();
    new Thread(new QuestionPoster()).start();
    new Thread(new MailReader()).start();
  }
}

This allows the full gamut of possibilities without any additional grok effort. If you want more mail answered than questions posted, make more MailReaders.

If you see

for ( int i = 0; i < 10; i++ ) {
  new Thread(new MailReader()).start();
}

you know exactly what is intended and you know that will work.

Upvotes: 1

Alex D
Alex D

Reputation: 30445

If you are building a utility for other programmers to use, note that the client programmer may not care about threads at all and may just want to write a single-threaded program. Unless there is a very good reason to do so, you shouldn't force them to drag threading issues into a program which would otherwise work fine single-threaded. Does this mean your library can't use threads internally? No! But to a caller, your methods should appear single-threaded (except that they return faster than they would if they were implemented without threads).

How can you do this? When someone calls into one of your methods, block the calling thread, and pass the task off to a pool of worker threads, who can perform it in parallel. After the worker threads finish the task, unblock the calling thread and let it return a value to the caller.

This way you can get the performance benefits of parallelism, without forcing callers to deal with threading issues.

Now, on the other hand, even if you decide that your library doesn't need to use threads internally, you should still make it thread-safe, because client programmers may want to use threads.

In other words, there is no reason why the decisions of "thread in method?" and "method in thread?" need to be coupled. You can use "thread in method" if there are performance benefits to doing so, but that shouldn't affect the caller. (They should just be able to call the method and get the needed return value back, without worrying about whether you are using threads internally).

If your module is thread-safe, then it won't be affected either by whether the caller is using threads or not. So if the client programmer wants to use threads, they can also use "method in thread". In some situations, you may have both "method in thread" and "thread in method" -- your module may be using a worker thread pool + task queue internally, and you may have multiple caller threads pushing tasks onto the queue and waiting for results.

Now, while I am talking like you are building a library, in reality you are probably just building code for your own use. But regardless of that, the same principles apply. If you want to use threads for performance, it is better to encapsulate the use of threads behind an interface, and make it so the rest of the program doesn't have to know or care whether module XYZ is using threads or not. At the same time, it is best if you make each module thread-safe, so callers can decide whether to use threads or not.

Upvotes: 0

nobeh
nobeh

Reputation: 10039

Method within Thread

  • [+] If your methods do not need to ensure the property of concurrent execution, or they have deterministic runtime behavior (time and performance), this approach can be a high-level management for concurrency of the application; i.e. concurrency remains at the level of objects rather than methods.
  • [-] Since the concurrency remains at the level of threads/objects, the application may lose the notion of responsiveness. A user may be "posting a question" while another is "fetch an answer"; and both can be dealt with concurrently.

Thread with Method

  • [+] More fine-grained concurrency control: each method becomes a unit of execution at the OS level. That's why as @LouisWasserman mentioned, maybe, taking advantage of Executor framework would make more sense.
  • [-] Generally threads are resourceful and expensive; so this means that you will have performance issues when used in high-frequency/load application with numerous calls to one method. Specially, if there are inter-method data/logic dependencies. In this regard, synchronization also becomes a concerns and that's why using Actor models can help more.

I'd suggest reading more about Actor models and their available implementations.

Upvotes: 4

Ehsan Khodarahmi
Ehsan Khodarahmi

Reputation: 4922

At first design (A), every method is a SEPARATE THREAD in fact, while at second design (B), you have ONLY ONE THREAD.
It deeply depends on you application logic & the operation which every method performs:
If you need to run your methods parallel, then A is the correct answer, but if you need execute all methods sequentially in a thread, then B would be your choice.

Upvotes: 0

Louis Wasserman
Louis Wasserman

Reputation: 198033

The second option is more amenable to being rewritten to use Executors and the like, so I'd prefer that version.

Upvotes: 4

Related Questions