0

In the code below I want Thread t1 to execute produce of Runnable and Thread t2 to execute consume of Runnable. Will this work ?

class Processor implements Runnable {
    @override
    run(){
        produce();
        consume();
    }
    void produce(){
        // code to produce, synchronize
    }
    void consume(){
        // code to consume, synchronize
    }
}

Class App {
    public static void main(String[] args){
        Processor p = new Processor()
        Thread t1 = new Thread(p);
        t1.start();
        Thread t2 = new Thread(p); 
        t2.start();
    }
}
Gray
  • 115,027
  • 24
  • 293
  • 354
Phoenix
  • 8,695
  • 16
  • 55
  • 88
  • 3
    What happens when you try it? What makes you think only one half of the run() method would be executed by one thread, and only the other half by the second thread? – JB Nizet Jun 24 '13 at 20:34
  • Possible duplicate of http://stackoverflow.com/q/9562505/877472. And as others have said, if both `produce()` and `consume()` are being called in the `run()` method without any way alter program flow, both threads are going to operate in the exact same fashion. – Paul Richter Jun 24 '13 at 20:37
  • Actually, in your code, _neither_ thread actually ever starts running - the main thread executes the contents of both their `run()` methods itself. – AJMansfield Jun 24 '13 at 20:41

4 Answers4

3

In the code below I want Thread t1 to execute produce of Runnable and Thread t2 to execute consume of Runnable.

The first answer is that most likely you don't want to do this. You should have a producer class and a consumer class. If they need to share data then fine but you should separate your producer and consumer code for modularity purposes. For example, the producer and consumer code could share a BlockingQueue that would be passed into both classes and used for them to exchange work.

As your code is currently written, each of the threads is obviously just going to call produce() and then consume(). I assume the code was written as an example.

If you really wanted to combine the producer and consumer code in the same class, you could pass some sort of boolean or other selector to tell the thread to either produce or consume.

For example:

 public class ProducerConsumerRunnable implements Runnable {
      private final Processor processor;
      private final boolean consume;
      public ProducerConsumerRunnable(Processor processor, boolean consume) {
          this.processor = processor;
          this.consume = consume;
      }
      public void run() {
          if (consume) {
              processor.consume()
          } else {
              processor.produce()
          }
      }
 }

So then you would start your threads like:

Processor p = new Processor()
Thread producerThread = new Thread(new ProducerConsumerRunnable(p, false));
producerThread.start();
Thread consumerThread = new Thread(new ProducerConsumerRunnable(p, true));
consumerThread.start();

Edit:

Initial your code was calling thread.run() when you should be calling thread.start(). Calling run() will just run the runnable in the foreground thread while start() actually forks a thread in the background that then calls run.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • Is there a reason you created another class instead of modifying processor itself to store the boolean value ? – Phoenix Jun 24 '13 at 20:55
  • No reason @Phoenix except that I thought you wanted to share the same `Processor` instance. – Gray Jun 24 '13 at 20:56
  • Yes. So can I create an arrayblocking queue in the main method and have processor implement runnable and store a class variable reference to same arrayblocking queue and pass the same processor to both the threads ? – Phoenix Jun 24 '13 at 21:07
0

No. Both threads would call produce and consume.

You should create 2 different runnables. One for the produce routine, and one for the consume routine.

Have one thread execute the produce runnable, and one thread execute the consume runnable.

William Morrison
  • 10,953
  • 2
  • 31
  • 48
0

The correct way to do this:

class App {
    public static void main(String[] args){
        Thread t1 = new Thread(){
            @Override run(){
                //insert produce method here
            }
        }
        Thread t2 = new Thread(){
            @Override run(){
                //insert consume method here
            }
        }
        t1.start(); // NOT run()!
        t2.start();
    }
}

This way, any shared variables that you would need between the two threads you can just add to the App class.

Also, as I pointed out in the code, you use Thread.start() to start a new thread, not Thread.run().

AJMansfield
  • 4,039
  • 3
  • 29
  • 50
0

As written, both threads will make both function calls. Most situations like this, you'd probably be best off putting the produce() and consume() functions in different classes; if there's a lot of other, shared logic, use inheritance to make them both subclasses off some common base class (possibly abstract if need be), which implements the shared logic.

If they absolutely, positively must be the same class (which they probably don't), you can try adding a Boolean to the Processor class, something like

class Processor implements Runnable
{
public Boolean producer;
@override
run()
{
if(producer){
    produce();
}
else{
    consume();
}
}
void produce()
{
// code to produce, synchronize
}
void consume()
{
// code to consume, synchronize
}
}

And set producer to false in one, true in the other before running them.

Billy Mailman
  • 272
  • 11
  • 25