0

Description of how i want the output : I want two threads Gaurav and john to complete a while loop(from 1 to 8), such that whichever thread starts ist, runs for 5 iterations(i.e. till count=5) , then go to sleep and then next thread completes the loop (run for count=6 to count=8). Program should end then. For this scenario , i created a instance variable count and incrementing its value in counter method

Problem is : i am getting a weird output (output attached at the end ) even after synchronizing the counter method (counter method increments count variable)

public class ThreadCounter implements Runnable {
   private int count; 
   @Override
   public void run(){

      try {
            counter(); // call synchronized counter function 

       } catch (InterruptedException e) {
        // TODO Auto-generated catch block
         e.printStackTrace();
         }

     }//end of run()

    public synchronized void counter() throws InterruptedException{

           while(true){

           // i want the loop to increment count from 1 to 4 by ist      thread(whichever thread runs ist) and then 5 to 8 by next thread

                 System.out.println("Which thread running ? " +Thread.currentThread().getName());

                 count++;

                 System.out.println("count is"+count);

                 if (count==5){
             System.out.println("count is"+count +" and Thread is " +Thread.currentThread().getName());
            // when count is 5 make the current thread should  go to sleep
               Thread.currentThread().sleep(7000);
              }// if count==5 ends here


        //whichever thread starts now , should start the counter from count=5 

             if (count==8){
                break;
            // when count is 5 make the current thread go to sleep

              }

          }// while loop ends here
   }// end of counter()
}// end of class ThreadingIst

 public class ThreadTest {

    public static void main(String [] args){

        Thread t1= new Thread(new ThreadingIst());

        Thread t2= new Thread(new ThreadingIst());  

        t1.setName("John");
        t2.setName("Gaurav");

    t1.start();
    t2.start();

   }// main ends here

}

Output is :

Which thread running ? John count is1

Which thread running ? John count is2

Which thread running ? John count is3

Which thread running ? John count is4

Which thread running ? John count is5

count is5 and Thread Johnis going to sleep

Which thread running ? Gaurav count is1

Which thread running ? Gaurav count is2

Which thread running ? Gaurav count is3

Which thread running ? Gaurav count is4

Which thread running ? Gaurav count is5

count is5 and Thread Gauravis going to sleep

Which thread running ? Gaurav count is6

Which thread running ? Gaurav count is7

Which thread running ? Gaurav count is8

count is8 and Thread Gauravis coming out of loop

Which thread running ? John count is6

Which thread running ? John count is7

Which thread running ? John count is8

count is8 and Thread Johnis coming out of loop

I have gone through an answer - "implements Runnable" vs. "extends Thread" , in which one of the comment is However, one significant difference between implementing Runnable and extending Thread is that by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.

so , if threads can share the same object , then the instance value like count should be shared by both. Why is my output like this then.

Community
  • 1
  • 1
Deen John
  • 3,522
  • 4
  • 29
  • 32
  • 1
    You will have to use the *same* `runnable` instance in `new Thread(..)` . Two different runnable instances means two different values of loop counter. Also, you need to make the counter `volatile`. – TheLostMind Jan 30 '15 at 13:27
  • @Don : thanks for pointing out that error . I have made the changes now- ThreadingCounter t= new ThreadingCounter(); Thread t1= new Thread(t); Thread t2= new Thread(t); – Deen John Jan 30 '15 at 13:36
  • @Don : even after doing that , i am not getting the correct output . 2nd thread is going in infinite loop. Any solution ? – Deen John Jan 30 '15 at 13:39
  • 2
    @Naruto_Uzumaki - Another thing.. `sleep()` doesn't release the lock / monitor. So you will have to use `wait()` and `notify()`. – TheLostMind Jan 30 '15 at 13:39
  • 1
    @TheLostMind : thanks i read more about sleep() method,sleep () won't work . Have to use wait () and notify() – Deen John Jan 30 '15 at 14:29

2 Answers2

1

A simple solution is to use the Java 8 Streams API

IntStream.rangeClosed(1, 8).parallel()
         .forEach(System.out::println);

This can use all the CPUs in your machine with a lot less code.

by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.

Actually it makes no difference in this regard, you can do either in both cases.

The reason to avoid sub-classing Thread is to avoid confusion when calling overridden methods.

Why is my output like this then.

You are sharing an object without thread safety.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • @Peter Lawrey : thanks , the code you mentioned could work . but i am new to Multi threading , so could you please mention any other change i can make with my code. I – Deen John Jan 30 '15 at 14:45
  • 1
    @Naruto_Uzumaki most of your code would disappear. I have added more feedback on your question. – Peter Lawrey Jan 30 '15 at 15:32
1

To achieve that you can create two threads, and make one waiting for the other, you can read about joining a thread here:

http://docs.oracle.com/javase/tutorial/essential/concurrency/join.html

I was thinking in something like:

public class Counter extends Thread {
    private final int countFrom;
    private final int countTo;
    private final Counter counterToWaitFor;

    public Counter(final int countFrom, final int countTo, final Counter counterToWaitFor) {
        super();
        this.countFrom = countFrom;
        this.countTo = countTo;
        this.counterToWaitFor = counterToWaitFor;
    }

    @Override
    public void run() {
        if (this.counterToWaitFor != null) {
            try {
                this.counterToWaitFor.join();
            } catch (final InterruptedException e) {
                e.printStackTrace();
            }
        }
        for (int i = this.countFrom; i <= this.countTo; i++) {
            System.out.println("i= " + i);
        }
    }
}

and in the main:

public static void main(final String[] args) throws IOException, InterruptedException {
    final Counter t1 = new Counter(1, 5, null);
    final Counter t2 = new Counter(6, 8, t1);
    t1.start();
    t2.start();
}
jjlema
  • 850
  • 5
  • 8
  • jjlema- could you please point out where in code i made changes for join. – Deen John Jan 30 '15 at 13:41
  • jjlema - great.i understood now.... final Counter t1 = new Counter(1, 5, null); and if (this.counterToWaitFor != null) { try { this.counterToWaitFor.join(); both make sure that only the t1 starts and finish ist – Deen John Jan 30 '15 at 14:51
  • @ jjlema : i tried this for runnable : if (!(Thread.currentThread().getName().equals("John"))){ Thread.currentThread().join(); } // but didn't work correctly – Deen John Jan 30 '15 at 15:20
  • @Naruto_Uzumaki you should do join over the thread that you what to wait for. – jjlema Jan 30 '15 at 16:38