rogerthat
rogerthat

Reputation: 1815

how to have a thread in java read the values of two seperate threads

ok. I need to make three threads: one to get odd numbers, one to get evens, and one to add the odd and evens together. The output would be something like this (1,2,3,3,4,7...). I'm new to threads and still shaky on how they work but this is what I have so far:

class even extends Thread 
{
    public void even()
    {
        Thread ThreadEven = new Thread(this); 
        start(); 
    } 
    public void run() 
    {
        try
        {
            for(int i = 0; i < 10; i += 2) 
            {
                System.out.println(i);
            }
            Thread.sleep(1000);
        }
        catch(Exception e) 
        {
            System.out.println("Error: Thread Interrupted");
        } 
    } 
}

class odd extends Thread 
{ 
    public void odd() 
    {
        Thread ThreadOdd = new Thread(this); 
        start(); 
    } 
    public void run() 
    {
        try
        {
            for(int i = 1;i < 10; i += 2) 
            System.out.println(i);
            Thread.sleep(1000);
        }
        catch(Exception e) 
        {
            System.out.println("Error: Thread Interrupted");
        } 
    } 
}
class ThreadEvenOdd
{
    public static void main(String args []) 
    {
        even e = new even();
        odd o = new odd();

    } 
} 

This prints out 0,2,4...and then 1,3,5. How to interleave? And is interleaving what I want and should I synchronize the threads as well? What I don't understand is how to get the values of the odd and even thread into a third to add the sum. Apologies beforehand if I didn't get the formatting correct for the code.

Upvotes: 0

Views: 403

Answers (2)

Thomas W
Thomas W

Reputation: 14164

you need a way of "passing" the numbers from your producer threads (even & odd) to your "consumer" thread.

'Simplest' but not best way is a mutable array, with one entry -- and you'll have to synchronize/ lock on something (the array?) to avoid concurrent threads corrupting it.

Perhaps the easier & better way, might be to use a 'double-ended queue' such as ArrayDeque. This lets values be put in at one end, and removed from the other. Again, access to it needs to be synchronized.

Create the queues external to all threads, then pass them in/ or make them visible.

class Example {
    protected Deque<Integer> queueEven = new ArrayDeque<Integer>();
    protected Deque<Integer> queueOdd = new ArrayDeque<Integer>();
    // you can synchronize on some mutable flag to finish, too.

    class Even extends Thread {
        public void run() {
            for (int i = 0; i < 10; i += 2) {
                synchronized (queueEven) {
                    queueEven.add( i);
                }
            }
        } 
    } 

    class Odd extends Thread {
        public void run() {
            for (int i = 1; i < 10; i += 2) {
                synchronized (queueOdd) {
                    queueOdd.add( i);
                }
            }
        } 
    } 

    class AddEvenOdd extends Thread {
        public void run() {
             while (true) {
                 int even;
                 synchronized (queueEven) {
                     even = queueEven.removeFirst();
                 }
                 int odd;
                 synchronized (queueOdd) {
                     odd = queueOdd.removeFirst();
                 }
                 int result = even + odd;
                 System.out.println("result="+result);
             }
        }
    }
}

Upvotes: 0

Guido Simone
Guido Simone

Reputation: 7952

As noted, this is kind of an advanced problem and yes you should be reading lots of tutorials before attempting this. Even for this short program I could never have written it if I had not spent quite a bit of time poring over Java Concurrency in Practice. (Hint - buy the book. It's all in there.)

The class even and odd are producers. The class sum is a consumer. The producers and consumers share a blocking queue to pass data. The producers use a negative number as a poison pill to indicate that they are finished and no more data will be forthcoming. When the consumer detects the poison pill it decrements the countDown latch. The main thread uses this as a signal that the work is complete.

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;


public class OddEven
{
   public static void main(String [] args) throws InterruptedException
   {
      BlockingQueue<Integer> evens = new ArrayBlockingQueue<Integer>(1);
      BlockingQueue<Integer> odds = new ArrayBlockingQueue<Integer>(1);
      even e = new even(evens);
      odd o = new odd(odds);
      sum s = new sum(evens, odds);

      e.start();
      o.start();
      s.start();
      s.waitUntilDone();
   }
}

class sum extends Thread
{
    private final BlockingQueue<Integer> in1;
    private final BlockingQueue<Integer> in2;

    private final CountDownLatch done = new CountDownLatch(1);
    public sum(BlockingQueue<Integer> in1, BlockingQueue<Integer> in2)
    {
        this.in1 = in1;
        this.in2 = in2;
    }

    public void waitUntilDone() throws InterruptedException
    {
       done.await();
    }
    public void run()
    {
        try
        {
           while (true)
           {
              int a = in1.take();
              int b = in2.take();
              if (a == -1 && b == -1)
                 break;

              int c = a + b;
              System.out.println(a);
              System.out.println(b);
              System.out.println(c);
           }
           done.countDown();
        }
        catch(Exception e)
        {
            System.out.println("Error: Thread Interrupted");
        }
    }
}

class even extends Thread
{
    private final BlockingQueue<Integer> out;

    public even(BlockingQueue<Integer> out)
    {
       this.out = out;
    }
    public void run()
    {
        try
        {
            for(int i = 0; i < 10; i += 2)
               out.put(i);

            out.put(-1);
        }
        catch(Exception e)
        {
            System.out.println("Error: Thread Interrupted");
        }
    }
}

class odd extends Thread
{
   private final BlockingQueue<Integer> out;

   public odd(BlockingQueue<Integer> out)
   {
      this.out = out;
   }
    public void run()
    {
        try
        {
            for(int i = 1;i < 10; i += 2)
               out.put(i);

           out.put(-1);
        }
        catch(Exception e)
        {
            System.out.println("Error: Thread Interrupted");
        }
    }
}

Typical output is:

0
1
1
2
3
5
4
5
9
6
7
13
8
9
17
Sums are complete

Upvotes: 1

Related Questions