How do I make concurrently running threads?
Asked Answered
S

3

5

I want to have two separate threads running two different instances of different classes and I want them to execute the run command at the same time.

I've made a practice class to demonstrate the problem I'm having. One racer counts forwards, the other counts backwards.

public class testCount {

    public static void main(String args[]) {
        testCount countCompetition = new testCount();
        countCompetition.run();
    }

    public void run() {
        (new Thread(new racer1())).start();
        (new Thread(new racer2())).start();
    }

    public class racer1 implements Runnable {
        public void run() {
            for(int x = 0; x < 100; x++) {
                System.out.println(x);
            }
        }
    }
    public class racer2 implements Runnable {
        public void run() {
            for(int y = 100; y > 0; y--) {
                System.out.println(y);
            }
        }
    }
}

My results

1
2
... All the way to 100
100
100
99
... All the way back down
1

What I want

1
100
2
99
3
98

They don't need to be taking turns like that, but they do need to be working at the same time, instead of one after the other. Any hints, advice or code snippets would be greatly appreciated.

Senary answered 19/4, 2013 at 7:59 Comment(0)
I
1

Just add Thread.sleep(1); in each racer class after System.out.println().

i.e. it will look like this:

public class racer1 implements Runnable {
    public void run() {
        for(int x = 0; x < 100; x++) {
            System.out.println(x);
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}
Insecticide answered 19/4, 2013 at 8:2 Comment(9)
@Senary the problem with not having them wait/sleep is that the first thread will be busy 100 % of the time, so the second thread won't get allocated any CPU time.Ilion
it will also not guarantee it that threads will run one after the other. You need to wait and notify each other when they have finished the taskTabling
Thanks for the advice. Luckily, the threads alternating is not essential for this part of my project. I will keep it in mind in future.Senary
It is not about alternating threads, but Thread.sleep() should be avoided !Copra
@NoobUnChained really? Can you argument your statement about avoidance of Thread.sleep()?Insecticide
@Insecticide Thread.sleep has never ever be a way to avoid race condition, and worst, it consumes more CPU for..nothing if it wakes up and than the condition (other thread job) is not made yet. In your case, it's totally possible to generate outcomes unexpected (cause unordered). One of the best way to manage your case: docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/… (better than traditional basic wait/notify)Foreshadow
@Foreshadow ups, guys, as I see, you didn't fully understand the task of question-maker. He just wants to thread work in parallel. He doesn't need to do some wait() - notify() mechanism absolutely.Insecticide
@Insecticide Indeed, I've just read the "hidden" last sentence of his question: "They don't need to be taking turns like that". :)Foreshadow
@NoobUnChained - not quite. Thread.sleep() should be avoided for the purpose of inter-thread communication, yes, but there is no reason to avoid it for other purposes.Orelee
P
7

I think all the answers so far are missing the point.

Your existing logic does enable your two threads to both execute concurrently, but this is not evident because your numbers only go up to 100, and the execution will usually stay with a specific thread for more than 1 instruction at a time, otherwise there would be a large amount of overhead in switching between the currently executing thread all the time. In your case, the JVM is deciding to execute your first thread long enough for it to print out 100 numbers before "context switching" to the 2nd thread. The JVM might choose to execute the threads differently, so the result you are seeing is not guaranteed to be the same every time.

If you increase your numbers even to 1000 you will (probably) see the two threads interleaving somewhat. You will still have large runs where one thread prints out a lot of numbers in a row because it is more efficient for the JVM to execute one thread for a while before switching, instead of context switching between every instruction.

Adding Thread.sleep(1) is not a good solution as you are adding an unneccessary delay. Sure, for 100 numbers this might not be noticable but for 10000 numbers you would have a delay of 10 seconds.

Is there any reason that you would require them to interleave to a higher degree than they already do? If there is then your simple model of running two threads concurrently is not sufficient. If not then just let the JVM decide the best order to run your threads in (which in the simple example you have given, means they probably won't interleave most of the time).

Publus answered 19/4, 2013 at 8:51 Comment(1)
I have no idea why you were downvoted for this analysis. Correcting it with an upvote.Orelee
I
1

Just add Thread.sleep(1); in each racer class after System.out.println().

i.e. it will look like this:

public class racer1 implements Runnable {
    public void run() {
        for(int x = 0; x < 100; x++) {
            System.out.println(x);
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}
Insecticide answered 19/4, 2013 at 8:2 Comment(9)
@Senary the problem with not having them wait/sleep is that the first thread will be busy 100 % of the time, so the second thread won't get allocated any CPU time.Ilion
it will also not guarantee it that threads will run one after the other. You need to wait and notify each other when they have finished the taskTabling
Thanks for the advice. Luckily, the threads alternating is not essential for this part of my project. I will keep it in mind in future.Senary
It is not about alternating threads, but Thread.sleep() should be avoided !Copra
@NoobUnChained really? Can you argument your statement about avoidance of Thread.sleep()?Insecticide
@Insecticide Thread.sleep has never ever be a way to avoid race condition, and worst, it consumes more CPU for..nothing if it wakes up and than the condition (other thread job) is not made yet. In your case, it's totally possible to generate outcomes unexpected (cause unordered). One of the best way to manage your case: docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/… (better than traditional basic wait/notify)Foreshadow
@Foreshadow ups, guys, as I see, you didn't fully understand the task of question-maker. He just wants to thread work in parallel. He doesn't need to do some wait() - notify() mechanism absolutely.Insecticide
@Insecticide Indeed, I've just read the "hidden" last sentence of his question: "They don't need to be taking turns like that". :)Foreshadow
@NoobUnChained - not quite. Thread.sleep() should be avoided for the purpose of inter-thread communication, yes, but there is no reason to avoid it for other purposes.Orelee
T
-1

You need to write a basic wait and notify system. One task needs to notify the other that he has fished the work. Basic idea can be derived from below code. create 2 tasks, one to count forward and one to count backward

Runnable task = new Runnable() {
  public void run() {
    System.out.println("woohooTwo");
    synchronized (t) {
      while (true) {
        System.out.println("---" + Thread.currentThread().getName() + "--" + t.i.getAndIncrement());
        t.notifyAll();

        try {
          Thread.sleep(1000);
          t.wait();
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }

    }
  }
};
Tabling answered 19/4, 2013 at 8:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.