0

I've been experimenting with multithreading and I'm really confused about a test I did. I had been doing research and everything was talking about how multithreading can allow 2 processes to run at the same time.

I made this program so 3 different threads would use a for loop to count 1-10, 11-20, and 21-30 so that I could see if they actually ran at the same time how I expected them to.

After running the program the output is something like 1 2 3 4 5 6 7 8 9 10 21 22 23 24 25 26 27 28 29 30 11 12 13 14 15 16 17 18 19 20 Basically any variation order of the 3 sets of numbers. So they can all be in order or have 21-30 before 11-20 sometimes. That doesn't seem like it is running at the same time, just running one after another.

In the for loop in the println(i); if i change it to println(i + "a"); for 1-10 and b, c for 11-20, 21-30 The output is actually in a random order like I had expected. Like this: 1a 11b 21c 2a 22c 12b 13b 23c 3a

Does the program know its doing nothing but counting up and just throw all the numbers on the screen without actually doing it? Or does adding the string at the end make it slow enough for the other threads to sneak in between the operations? I know nothing about this ha.

public class Run{

    static Runnable updatePosition;
    static Runnable render;
    static Runnable checkCollisions;

    public static void main(String[] args) {
        // System.out.println(Runtime.getRuntime().availableProcessors());

        updatePosition = new Runnable() {

            @Override
            public void run() {

                for (int i = 1; i <= 10; i++) {
                    System.out.println(i);
                }
            }

        };

        render = new Runnable() {

            @Override
            public void run() {
                for (int i = 11; i <= 20; i++) {
                    System.out.println(i);
                }

            }

        };

        checkCollisions = new Runnable() {

            @Override
            public void run() {
                for (int i = 21; i <= 30; i++) {
                    System.out.println(i);
                }

            }

        };

        Thread updatePositionThread = new Thread(updatePosition);
        Thread renderThread = new Thread(render);
        Thread checkCollisionsThread = new Thread(checkCollisions);
        updatePositionThread.start();
        renderThread.start();
        checkCollisionsThread.start();

    }

}

Also, how do threads get assigned to CPU cores? In depth please, reasonably. What I mean by asking this is: If I were to use a single thread program and use an update method and a draw method and they together took too long and made my program lag, would putting them on separate threads make this not help, or does it not actually run side by side? Assuming I can deal with all of the concurrency.

David ten Hove
  • 2,748
  • 18
  • 33
Sam Burns
  • 103
  • 12
  • Your test is a little strange. The work any runnable does (without appending a String) is so small, I can imagine the first thread being done before the next Thread's start method is even called. I bet if you have them print 10000 numbers instead, the numbers will be random even without appending a String. – David ten Hove Dec 05 '14 at 08:56
  • I just attempted this and the numbers do switch off, kind of. They go from like 1-5000 then 10000-15000 then 20000-25000 then 5k-7k pretty much from then on it goes by intervals of 2000 until each one finishes – Sam Burns Dec 05 '14 at 09:02
  • If you add a liberal quantity of `Thread.sleep()` you should find a much more understandable result. – OldCurmudgeon Dec 05 '14 at 09:22

1 Answers1

1

Actually, JIT optimizations, processor architecture and several other things play a part in how these kind of situations turn out.

The actual output should not be an ordered execution of threads like 1-10, 21-30, 11-20.

Changing your code a little to :

for (int i = 1; i <= 10000; i++)
for (int i = 10001; i <= 20000; i++)
for (int i = 20001; i <= 30000; i++)

I get (as expected, complete execution of one thread is not happening, as one might assume in your case). It is all about how much time a thread gets.

1
2
3
...
250
251
252
253
20001
20002
20003
...
20127
20128
10001
10002
10003
..

Changing i to "a" + i leads to dynamic construction of new Strings using StringBuilder, this will indeed take some time (and hence CPU cycles). On the other hand, primitive ints don't have this delay.. So, you get such an output.

TheLostMind
  • 35,966
  • 12
  • 68
  • 104
  • So in the case of having multiple thousands of numbers in a row then thousands more of another set, does this mean they are just taking turns in one processor? What do you mean by how much time a thread gets? – Sam Burns Dec 05 '14 at 09:16
  • @SamBurns - Yes, they are just taking turns on the CPU(s). If the *number* is less, then the *thread scheduling* algorithm might decide to *execute* the entire thread in one go. So, in your first case, the output seems to be *in order*. Whereas, if the numbers(iterations) are more, then the thread scheduler is forced to *preempt* the current thread to make way for other threads. – TheLostMind Dec 05 '14 at 09:20
  • So how can I program this in such a way that it will use more than one core? Or is that not possible? – Sam Burns Dec 05 '14 at 09:22
  • @SamBurns - In java you could find out how many cores / processors your program can use at start-up by using - `Runtime.getRuntime().availableProcessors();`. You don't have control over which core / processor a thread should use. Although there are things like *thread affinity* but they cannot be relied upon. – TheLostMind Dec 05 '14 at 09:26
  • @SamBurns - You might want to look [here](http://stackoverflow.com/questions/2238272/java-thread-affinity) – TheLostMind Dec 05 '14 at 09:28