Solved

output

Posted on 1998-04-11
8
241 Views
Last Modified: 2010-04-16
In the following program, I cannot figure out why my output does not display properly.  It is suppose to output three pieces of data on the same line and go to the next line.  I am using a static var called count  and with the test output I have included in the method printOutput it shows me that count does not increment as it should.

import java.io.*;

public class prog_7 {

   public static void main(String args[]) throws IOException {
      BufferedReader myin = new BufferedReader(new InputStreamReader(System.in));
      CubbyHole c = new CubbyHole();
      int lastNumber = 100;

      MyThread thread = new MyThread("thread0" + Integer.toString(2), 2, c);
      thread.start();

      for (int i = 3; i <= lastNumber; i++) {
         try {
            c.put(i);
         } catch (InterruptedException ie) {}
      }

      try {
         c.put(-1); //stop request
      } catch (InterruptedException ie) {}

   } // end main

} //end class prog_7


class MyThread extends Thread {
   static int count = 0;
   int primeNumber;
   CubbyHole in_cubby;
   MyThread next_thread;
   CubbyHole next_cubby;
   boolean running;

   MyThread(String name, int pNum, CubbyHole c) {
      setName(name);
      primeNumber = pNum;
      in_cubby = c;
      next_cubby = new CubbyHole();
      next_thread = null;
      running = true;
   }

   public void run() {
      while (running) {
         try {
            int testNum = in_cubby.get();
            if (testNum > 0) {
               if (testNum % primeNumber != 0) {
                  printOutput(testNum);
                  if (next_thread == null) {
                     initializeThread(testNum);
                  }
                  next_cubby.put(testNum);
               }
            }
            else {  // stop request;
               running = false;
               next_cubby.put(testNum); //propagate stop request;
            }
         } catch(InterruptedException ie) {}
      }
   }

   public void initializeThread(int testNum) {
      if (testNum < 10) {
         next_thread = new MyThread("thread0" +Integer.toString(testNum),
                                                         testNum, next_cubby);
      }
      else {
         next_thread = new MyThread("thread" +Integer.toString(testNum),
                                                         testNum, next_cubby);
      }
      next_thread.start();
   }

   public synchronized void printOutput(int testNum) {
      count++;
      if (count % 3 == 0) {
//         System.out.println(getName() + " processing " + testNum);
         System.out.println(String.valueOf(count));
      }
      else {
//         System.out.print(getName() + " processing " + testNum + " ** ");
         System.out.print(String.valueOf(count) + " ** ");
      }
   }

   public void stopRequest() {
      if (next_thread != null) {
         next_thread.stopRequest();
      }
      running = false;
      this.interrupt();
   }

} //end class MyThread


class CubbyHole {
   boolean new_data;
   int data;

   public CubbyHole() {
      data = 0;
      new_data = false;
   }

   public synchronized void put(int number) throws InterruptedException {
      while (new_data) {
         wait();
      }
      data = number;
      new_data = true;
      notifyAll();
   }

   public synchronized int get() throws InterruptedException {
      while (!new_data) {
         wait();
      }
      new_data = false;
      notifyAll();
      return data;
   }

} //end class CubbyHole
0
Comment
Question by:bellamy
8 Comments
 

Author Comment

by:bellamy
ID: 1234032
Adjusted points to 100
0
 
LVL 16

Expert Comment

by:imladris
ID: 1234033
Could you include a sample of the output that you get, and a
sample of what you expect?

Recall that the threads are executing concurrently, and so the
display will be as well.

0
 

Author Comment

by:bellamy
ID: 1234034
The following is a sample run of the program.  As you can notice I am sending count to the output in order for you to see that the count is not incrementing properly all of the time.  Each line of output should have three numbers on it and since I mod by 3 it should begin a new line after every third output.  The first two output include the two astericks and the last one does not.  As you scroll down this output you will see the count is not always what it should be and because of that neither is the format of the output.


1 ** 2 ** 3
4 ** 5 ** 6
7 ** 8 ** 9
10 ** 11 ** 12
13 ** 14 ** 15
16 ** 17 ** 18
19 ** 20 ** 21
22 ** 23 ** 24
25 ** 26 ** 27
28 ** 29 ** 30
31 ** 32 ** 33
34 ** 35 ** 36
37 ** 38 ** 39
40 ** 41 ** 42
43 ** 44 ** 45
46 ** 47 ** 48
49 ** 50 ** 51
52 ** 53 ** 54
55 ** 56 ** 57
58 ** 59 ** 60
61 ** 62 ** 63
64 ** 65 ** 66
67 ** 68 ** 69
70 ** 71 ** 72
73 ** 74 ** 75
76 ** 77 ** 78
79 ** 80 ** 81
82 ** 83 ** 84
85 ** 86 ** 87
88 ** 89 ** 90
91 ** 92 ** 93
94 ** 95 ** 96
97 ** 98 ** 99
100 ** 101 ** 102
103 ** 105
104 ** 106 ** 107 ** 108
109 ** 110 ** 111
112 ** 113 ** 114
115 ** 116 ** 117
118 ** 119 ** 120
121 ** 122 ** 123
124 ** 125 ** 126
127 ** 128 ** 129
130 ** 131 ** 132
133 ** 134 ** 135
136 ** 137 ** 138
139 ** 140 ** 141
142 ** 143 ** 144
145 ** 146 ** 147
148 ** 149 ** 150
151 ** 152 ** 153
154 ** 155 ** 156
157 ** 158 ** 159
160 ** 161 ** 162
163 ** 164 ** 165
166 ** 167 ** 168
169 ** 170 ** 171
172 ** 173 ** 174
175 ** 176 ** 177
178 ** 179 ** 180
181 ** 182 ** 183
184 ** 185 ** 186
187 ** 188 ** 189
190 ** 191 ** 192
193 ** 194 ** 195
196 ** 197 ** 198
199 ** 200 ** 201
203 ** 204
202 ** 205 ** 206 ** 207
208 ** 209 ** 210
211 ** 212 ** 213
214 ** 215 ** 217 ** 218 ** 219
220 ** 221 ** 222
223 ** 216
224 ** 225
226 ** 227 ** 228
229 ** 230 ** 231
232 ** 233 ** 234
235 ** 236 ** 237
238 ** 239 ** 240
241 ** 242 ** 243
244 ** 245 ** 246
247 ** 248 ** 249
250 ** 251 ** 252
253 ** 254 ** 255
256 ** 257 ** 258
259 ** 260 ** 261
262 ** 263 ** 264
265 ** 266 ** 267
268 ** 269 ** 270
272 ** 273
274 ** 271 ** 275 ** 276
277 ** 278 ** 279
280 ** 281 ** 282
283 ** 284 ** 285
286 ** 287 ** 288
289 ** 290 ** 291
292 ** 293 ** 294
295 ** 296 ** 297
298 ** 299 ** 300
301 ** 302 ** 303
304 ** 305 ** 306
307 ** 308 ** 309
310 ** 311 ** 312
313 ** 314 ** 315
316 ** 317 ** 318
319 ** 320 ** 321
322 ** 323 ** 324
325 ** 326 ** 327
328 ** 329 ** 330
331 ** 332 ** 333
334 ** 335 ** 336
337 **
0
 
LVL 6

Expert Comment

by:jpk041897
ID: 1234035
It looks like you are running into syncronization problems with the threads,I.e.: based on you run, it appears like you are generating more than one thread and your sync methodology is not blocking the code completley.

If nothing else fixes it you might need to implement a semaphore to control the output.

I'll monitor this thread to see if no one comes up with a better option, and if not I'll post you info on how to syncronize via semaphores.
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 6

Accepted Solution

by:
gadio earned 100 total points
ID: 1234036
Hi, bellamy.
Well, heres your prolem: You have synchronized the printOutput method, but the synchonization work on the current object. In your case it is the current MyThread object while you are touching the static variable. But each of them threads has different MyThread objects, so that actually any number of threads can be in the printOutput method in the same time! This is how you get to see these problems. What you need if you want to synchronize the access to a static var is a static synchronization. Try this I think it should work.

------
 

class MyThread extends Thread {
  static int count = 0;
  static Object sync_obj;  //  <--- NOTE.
  int primeNumber;
  CubbyHole in_cubby;
  MyThread next_thread;
  CubbyHole next_cubby;
  boolean running;
 
  MyThread(String name, int pNum, CubbyHole c) {
      setName(name);
      primeNumber = pNum;
      in_cubby = c;
      next_cubby = new CubbyHole();
      next_thread = null;
      running = true;
      sync_obj = new Object();
  }
 
  public void run() {
      while (running) {
        try {
            int testNum = in_cubby.get();
            if (testNum > 0) {
              if (testNum % primeNumber != 0) {
                  printOutput(testNum);
                  if (next_thread == null) {
                    initializeThread(testNum);
                  }
                  next_cubby.put(testNum);
              }
            }
            else {  // stop request;
              running = false;
              next_cubby.put(testNum); //propagate stop request;
            }
        } catch(InterruptedException ie) {}
      }
  }
 
  public void initializeThread(int testNum) {
      if (testNum < 10) {
        next_thread = new MyThread("thread0" +Integer.toString(testNum),
                                                 testNum, next_cubby);
      }
      else {
        next_thread = new MyThread("thread" +Integer.toString(testNum),
                                                 testNum, next_cubby);
      }
      next_thread.start();
  }
 
  public synchronized void printOutput(int testNum) {
      synchronized( sync_obj ) {  // <---- NOTE.
        count++;
        if (count % 3 == 0) {
            //         System.out.println(getName() + " processing " + testNum);
            System.out.println(String.valueOf(count));
        }
        else {
            //         System.out.print(getName() + " processing " + testNum + " ** ");
            System.out.print(String.valueOf(count) + " ** ");
        }
      }
  }
 
} //end class MyThread


-----

Note the sync_obj static object. Note also that the synchronized keyword is not really necesarry for the printOutput method since the synchronization work is done on the sync_obj object.
Let me know if it worked. If not we can try somthing different.
Regards,
G.

0
 

Author Comment

by:bellamy
ID: 1234037
Hi Gadio

Your fix works about 95% of the time, but when I increase the loop to test 500 numbers it messed up my output about half way through.  It did this every time.  I have to test the program using 500 as my lastNumber.  One thing I did not mention before was that the program runs fine (just like I sent it, even up to 500 as the lastNumber) on Unix, but not on WindowsNT or Windows95.

B
0
 
LVL 6

Expert Comment

by:gadio
ID: 1234038
  Yes, you are right. I guess that the JVM synchronization mechanizm in the win32 platforms has some bugs in it. Not a big surprise. This one is working (I tried it several times).

----

class MyThread extends Thread {
  static int count = 0;
  int primeNumber;
  CubbyHole in_cubby;
  MyThread next_thread;
  CubbyHole next_cubby;
  boolean running;

  MyThread(String name, int pNum, CubbyHole c) {
        setName(name);
        primeNumber = pNum;
        in_cubby = c;
        next_cubby = new CubbyHole();
        next_thread = null;
        running = true;
  }

  public void run() {
        while (running) {
          try {
                int testNum = in_cubby.get();
                if (testNum > 0) {
                  if (testNum % primeNumber != 0) {
                        printOutput(testNum);
                        if (next_thread == null) {
                          initializeThread(testNum);
                        }
                        next_cubby.put(testNum);
                  }
                }
                else {  // stop request;
                  running = false;
                  next_cubby.put(testNum); //propagate stop request;
                }
          } catch(InterruptedException ie) {}
        }
  }

  public void initializeThread(int testNum) {
        if (testNum < 10) {
          next_thread = new MyThread("thread0" +Integer.toString(testNum),
                                                                 testNum, next_cubby);
        }
        else {
          next_thread = new MyThread("thread" +Integer.toString(testNum),
                                                                 testNum, next_cubby);
        }
        next_thread.start();
  }

  public static synchronized void printOutput(int testNum) {
        count++;
        if (count % 3 == 0) {
          //         System.out.println(getName() + " processing " + testNum);
          System.out.println(String.valueOf(count));
        }
        else {
          //         System.out.print(getName() + " processing " + testNum + " ** ");
          System.out.print(String.valueOf(count) + " ** ");
        }
  }

} //end class MyThread

----
The only difference from your first implementation is the the printOut method is also static and therfor is the same one for all the instances.
G.

0
 

Author Comment

by:bellamy
ID: 1234039
Hey Gadio

Works great!!

Thanks
B.
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
The viewer will learn how to implement Singleton Design Pattern in Java.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now