1

I am just testing out some threads, trying to figure out how to use them. My question is, how can I get my current scenario to work how I want it?

I want to have this program print out 1 - 100. I have two methods; oddNumbers and evenNumbers

oddNumbers:

public static void oddNumbers() {
  new Thread(new Runnable() {
    public void run() {
      for (int i = 0; i < 100; i++) {
        if (i % 2 == 1) {
          System.out.println(i);
        }
      }
    }
  }).start();
}

evenNumbers:

public static void evenNumbers() {
  new Thread(new Runnable() {
    public void run() {
      for (int q = 0; q < 100; q++) {
        if (q % 2 == 0) {
          System.out.println(q);
        }
      }
    }
  }).start();
}

main method

public static void main(String[] args) {
  evenNumbers();
  oddNumbers();
}

So, from what I understand, the methods oddNumbers and evenNumbers are running on different threads. So if they are, then why isn't my output 1-100?

Here's the output I get:

0
2
4
6
.
.
.
50
1
3
5
.
.
.
99
52
54
56
.
.
.
100

About half way through the evenNumbers loop, the oddNumbers loop cuts it off. Why does this happen, and how do I set it up so that it'll print 1-100?

Thanks in advance!

Jonny Henly
  • 4,023
  • 4
  • 26
  • 43
Kaelinator
  • 360
  • 3
  • 17
  • 2
    Well, you start the even numbers thread before the odd numbers thread... But even if they started at the same time, why do you think they would alternate? – Andy Turner May 24 '16 at 20:31
  • I wasn't really expecting a perfect alternation, but I thought the numbers would be a bit mixed. I don't get why one for loop cuts another off, and why they can't go at the same time. @AndyTurner – Kaelinator May 24 '16 at 20:35
  • 1
    It's more likely your output buffers filling and being flushed to output than the actual execution time of the programs. Tack on a timestamp and you might see a bit more overlap. – Daniel Widdis May 24 '16 at 20:37
  • 7
    Reminds me of: *'A programmer had a problem. He thought to himself, "I know, I'll solve it with threads!". has Now problems. two he'* – zapl May 24 '16 at 20:37
  • 2
    @Kaelinator what to do you mean by "same time"? threads might be running at the same time on multi-core, but System.out.print has a synchronized block that serialises writes – Sleiman Jneidi May 24 '16 at 20:37
  • 2
    @Kaelinator well, like I say, you start one thread first - so it gets a way through its numbers before the other one starts; then the other one starts and "cuts off" the first thread. – Andy Turner May 24 '16 at 20:39
  • 1
    Thread scheduling is something you should know about, but try not to spend to much time thinking about. Try adding a Thread.yield after each System.out statement or Thread.sleep(1) – MadProgrammer May 24 '16 at 20:40

2 Answers2

3

Because you did not tell threads to wait remaining participants.

It is hard to tell if next thread continues its work just after started or how long it will take to start. It could be several cpu cycles or 2 seconds.

You want exact instruction timing for realtime critical app? Start fpga programming.

For this java pc program, you could have used cyclic barrier just to let them do steps together without any starting priority importance.

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Demo {
    public static CyclicBarrier barrier = new CyclicBarrier(2);
    public static void oddNumbers() {
          new Thread(new Runnable() {
            public void run() {
              for (int i = 0; i < 100; i++) {
                  try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if (i % 2 == 1) {
                  System.out.println(i);
                }
              }
            }
          }).start();
        }


        public static void evenNumbers() {
          new Thread(new Runnable() {
            public void run() {
              for (int q = 0; q < 100; q++) {
                  try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if (q % 2 == 0) {
                  System.out.println(q);
                }
              }
            }
          }).start();
        }


        public static void main(String[] args) {
          evenNumbers();
          oddNumbers();
        }
}

barrier instance is created here with room for 2 threads so every 2 await action resets it and threads can wait on it again on next iteration.

Still, it has probability to output:

1
0
3
2
5
4
...

instead of

0
1
2
3

it could be solved using a third action to combine 2 threads results before printing to console.

The hardness here is you ask for serial action in a multithreaded environment.

huseyin tugrul buyukisik
  • 11,469
  • 4
  • 45
  • 97
1

I understand you don't want them to be alternated, just understand why each is executed for so long.

That decision is taken by the scheduler of the operating system. It decides when to switch to another thread. The thing with your example is that your threads are so small, they are executed so quickly.

The scheduler gives the power to be executed to a thread for some time, the problem is, that time is enough to display so many numbers of your loop, so they are not switched many times.

You would get better results if you had it running longer, use much bigger numbers. Or, you can also make the loops take longer before printing, add some calculus that takes time, so that it doesn't print that many numbers in a row.

UDKOX
  • 738
  • 3
  • 15