1

I wrote a method that should be repeated 1000 times and the method is again another loop (like a nested loop).Since the running time was not reasonable I decided to write a thread to run it faster. Here is the method:

public class NewClass implements Runnable {
@Override
public void run() {
    for (int j = 0; j < 50; j++) {
        System.out.println(i+","+j);

        /*
         * 
         * my method
         */

    }  
  }
}

and here is the way the main class calls it:

for (int i = 0; i < 1000; i++) {

   NewClass myMethod = new NewClass();

   Thread thread = new Thread(myMethod);
   thread.start();
}

the problem is that when I run it, the thread skips the first iteration (when i=0) in the main class and then in the next iterations, it skips some iterations of inner loop (myMethod). Here is the result of println:

1,0
1,1
2,0
2,1
3,0
3,1
3,2
...
3,22
4,0
...

clearly it skips i=0 and for other iterations it cannot finish it. I'm sure the problem is not in the body of method. I run it several times without thread. It is the first time I write thread and I think the problem is in thread.

MTT
  • 5,113
  • 7
  • 35
  • 61
  • 2
    I don't think this code does what you think it does... if you want to divide up work among threads, you need to divide it and give a specific workload to each thread. This is interleaving and pretty much guaranteed that threads will interfere with each other. Also, please use the Concurrency framework. Java 5 introduced this a decade ago. –  Nov 27 '13 at 01:26
  • i starts at 1, how does it skip i = 0 – JRowan Nov 27 '13 at 01:28
  • @JRowan: You are right. It was my mistake. I fixed it. – MTT Nov 27 '13 at 01:29
  • @VTT You are not scheduling the execution of the 1000 threads you have created. And don't forget there is a main thread as well. What you are getting is because of Race condition. Read http://stackoverflow.com/questions/34510/what-is-a-race-condition – Prateek Nov 27 '13 at 01:32
  • @Prateek Thanks a lot. Based on my understanding Race condition happens when each iteration is dependent to other iterations. In my case all iterations are independent from each other. – MTT Nov 27 '13 at 01:44
  • 1
    `System.out.println(i+","+j);` << where is `i`? Something doesn't seem right that your local variable `i` is accessible from another thread. – ADTC Nov 27 '13 at 02:02

3 Answers3

2

Your loop index for i starts from 1 (I'm guessing? It's not even clear why it's in scope), so it's unsurprising that i = 0 does not occur. Similarly, I think you're confused about the printing order, which need not be deterministic. It may be printing the output interspersed with output from other threads. This is normal and expected. I think the code is behaving correctly, it might just not be doing what you want.

I noticed you edited your code. This doesn't really bode well for anybody being able to help you diagnose whatever unexpected behavior you're seeing.

Gian
  • 13,735
  • 44
  • 51
1

It just so happens that no thread calls the print function while i is zero. You don't compel this ordering, so it may or may not happen in that order. Either of these things can happen.

  1. i is zero
  2. A thread is created.
  3. The thread prints the value of i.
  4. i is incremented.

Or

  1. i is zero
  2. A thread is created.
  3. i is incremented.
  4. The thread prints the value of i.

Your code doesn't enforce either ordering, so it can happen either way. You only have guaranteed ordering between threads when something in your code guarantees such ordering.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Thanks a lot. As I mentioned I want to distribute the iterations of calling the method over threads but it skips some iterations of the inner loop. – MTT Nov 27 '13 at 01:42
  • Well your code bears no resemblance to what you claim you want to do. – David Schwartz Nov 27 '13 at 01:44
0

clearly it skips i=0 and for other iterations it cannot finish it. I'm sure the problem is not in the body of method. I run it several times without thread. It is the first time I write thread and I think the problem is in thread.

There are 2 reason why this could be happeneing.

  1. You seem to be printing out i which is a shared between threads without any memory synchronization. See the tutorial on memory synchronization. Each processor has internal cached memory so even though i is being modified in the main memory, the processor cache may still see the old value.

  2. You also are probably seeing a race condition. What is happening is that the first two threads (0 and 1) are started before either of their run() methods actually being called. So when they both run and print out 1 because that is what i's value is at the time.

Because of either or both of these reasons, if you run your application 10 times you should see vastly different output.

If you want i to be shared then you could turn it into an AtomicInteger and do something like:

final AtomicInteger i = new AtomicInteger(0);
...
// replacement for your for loop
i.set(0);
while (true) {
    if (i.incrementAndGet() >= 1000 {
       break;
    }
    ...
}
...
// inside the thread you would print
System.out.println(i + "," + j);

But this mechanism does not solve the race condition. Even better would be to pass in the i value to the NewClass constructor:

private int i;
public NetClass(int i) {
   this.i = i;
}
...

Then when you create the instances you do:

NewClass myMethod = new NewClass(i);
Gray
  • 115,027
  • 24
  • 293
  • 354