0

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.

Vikdor
  • 23,934
  • 10
  • 61
  • 84
rogerthat
  • 1,805
  • 4
  • 20
  • 34
  • 1
    Please take some time to reformat your code. It's pretty unreadable right now. Please see: http://meta.stackexchange.com/questions/22186/how-do-i-format-my-code-blocks#133010 – Gray Oct 06 '12 at 01:55
  • Also, you should never leak the `this` while in a object constructor. That sets up immediate race conditions. See: http://stackoverflow.com/questions/5623285/java-why-not-to-start-a-thread-in-the-constructor-how-to-terminate – Gray Oct 06 '12 at 01:56
  • 3
    *"Apologies beforehand if I didn't get the formatting correct for the code."* - Seriously, if you knew that the formatting was bad, it would have been more respectful of the readers to have fixed this BEFORE you hit the "post question" button. – Stephen C Oct 06 '12 at 02:06
  • This is my first post. I wasn't sure how to use the tags – rogerthat Oct 06 '12 at 02:08
  • 1
    It is still a mess. Replace ALL of the 'TAB' characters with spaces. – Stephen C Oct 06 '12 at 02:12
  • Should be reader friendlier now – rogerthat Oct 06 '12 at 02:28
  • 2
    In both your classes you're constructing a new `Thread` then immediately throwing it away. You then call `start()` from your constructor. Your class *is a* `Thread`; you extended it. And you shouldn't be calling `start()` like that. I really suggest the Oracle tutorial on threads (and possibly basic java) before you go further. – Brian Roach Oct 06 '12 at 03:10
  • @healix, this is still not reader friendly, really. You simply missed all of the standard Java style guidelines. Classes start with upper case letters, local variables and fields with lower case letters, you do not start a new line to open curly braces. Really, this code is HORRIBLE to read. It looks more like C# than Java. – Bruno Reis Oct 06 '12 at 04:53
  • @BrunoReis Well c/c++/c# is the land I'm coming from and it's hard to break out of those habits. But I'll get it in my head soon. Thanks for the tips, though. I don't know what you mean by "you don't start a new line to open curly braces." Are you talking my catch sysout? – rogerthat Oct 06 '12 at 06:06

2 Answers2

1

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
Guido Simone
  • 7,912
  • 2
  • 19
  • 21
  • Thanks. Great Explanation. Really, really appreciate it. I'm going to pick up that book as well. I'm also coming from a purely C/C++ background and it's hard to wrap my head around Java. Thread in particular. – rogerthat Oct 06 '12 at 03:54
0

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);
             }
        }
    }
}
Thomas W
  • 13,940
  • 4
  • 58
  • 76
  • 1
    I like these "producer" and "consumer" terms. It makes more sense when I'm trying to learn threads – rogerthat Oct 06 '12 at 04:21
  • After going through these two examples I can see how in depth threads are. It seems these queue's are a necessity – rogerthat Oct 06 '12 at 04:27