1 2 Previous Next 21 Replies Latest reply: Nov 20, 2008 12:44 PM by 807589 RSS

    Thread Synchronization

    807589
      I am currently using two threads to make/display modifications done to a Vector of objects. My code, for the most part works fine...my threads are synchronized and the modifications are all correct. However, I am having some problems formatting the output, especially when my thread throws exceptions when reading in the text file used for modifications.

      Run Method of Thread 1 (reads text file, parses)
      public void run(){
                try{
                     Thread.sleep(2000);
                }
                catch(InterruptedException e){ }               
                try{
                BufferedReader inFile = new BufferedReader(new FileReader("changes.txt"));
                line = inFile.readLine();
                StringTokenizer tokens;     
               if (line == null) 
                    System.exit(-1);
                    
               System.out.println("\n");       
                    while (line != null){
                          tokens = new StringTokenizer(line);
                          while (tokens.hasMoreTokens()){
                               try{            
                                   partID = Integer.parseInt(tokens.nextToken());
                                   changeType = tokens.nextToken();                        
                                   
                                   if (changeType.equals("delete")){
                                        if(pVec.idCheck(partID) == false){
                                             throw new NoSuchPartException();
                                        }
                                        else{ 
                                             pVec.changeVec(line);
                                        }                                                     
                                   }//end delete
                                   
                                   else if (changeType.equals("add")){ 
                                        partName = tokens.nextToken();            
                                         price = Double.parseDouble(tokens.nextToken());
                                        quantity = Integer.parseInt(tokens.nextToken());
                         
                                            strRating = tokens.nextToken();
                                            char[] convertToChar = strRating.toCharArray();
                                            rating = convertToChar[0];                                                   
        
                                        partType = tokens.nextToken();                          
                                        
                                        pVec.changeVec(line);                    
                                   }//end add
                                   else{
                                        throw new BadChangeException();
                                   }                                                 
                               }//end try
                               catch(BadChangeException e){
                                    System.out.println("Change is neither an add nor a delete!");
                                    numOfBadChanges++;
                                    break;
                               }
                               catch (NoSuchPartException e){
                                    numOfBadParts++;
                                    break;
                               }
                               catch (NumberFormatException e){                              
                                    System.out.println("NumberFormatException Thrown");
                                    numOfBadNums++;
                                    break;
                               }
                               catch (NoSuchElementException e){
                                    System.out.println("Part ID does not exist!");
                                    break;
                               }
                          }//end while has more tokens
                          line = inFile.readLine();     
                    }//end while line != null
                }//end first try          
                catch(FileNotFoundException e){
                     System.out.println("File Not Found!");
                     System.exit(0);
                }
                catch(IOException e){     }
                catch(ConcurrentModificationException e){  }
                
                pVec.setMoreData(false);
                p.setT1Done(true);               
           }//end run
      When I run the program, thread 1 is supposed to display the new part that is added/deleted, followed by thread 2 which will print out the new size of the vector and the names of all the objects in the vector. My output seems to have an issue when there is an exception caught within the method above. Here is the output:
      Thread One has ADDED a new part, PartA
      
              Message from Thread Two
              Size of Vector: 14
              /* 13 original parts */
              PartA           //new part has been added to the end of the Vector
      
      Thread One has DELETED PartB from the Vector
      Change is neither an add nor a delete!
      Change is neither an add nor a delete!
      
              Message from Thread Two
              Size of Vector: 13
              /* PartB has been successfully deleted */
      I need to move the "message from Thread Two" line to display immediately after "Thread One has DELETED...", but for some reason whenever there is an exception thrown, or multiple ones in this case, all of those exceptions are displayed before Thread 2 does its job.
        • 1. Re: Thread Synchronization
          800298
          You said thread 2 does something following thread 1. If they aren't running at the same time, why complicate things by having two threads?
          • 2. Re: Thread Synchronization
            807589
            Both threads are running at the same time. Thread one make modifications to the Vector and Thread two "scans" the Vector if any changes have been made.

            So, Thread one will read in the first line of the text file. If it is a valid add or delete, it will send it to another method that performs the adds/deletes. Then, after the part has been added/delete, it will wait and not do anything until Thread 2 scans the Vector and prints out the changes. It is the same setup to the producer/consumer problem...as a matter of fact, it is the same problem, just with different types of objects and requests.
            • 3. Re: Thread Synchronization
              800298
              I'm assuming that the wait/notify stuff is in the changeVec method. I need to see that and also thread 2 code.
              • 4. Re: Thread Synchronization
                807589
                Yes, you are correct.

                Here is thread two's run....It doesn't do much:
                public void run(){
                               while (partV.hasMoreData()){
                               try{
                                    Thread.sleep (2000);
                               }
                               catch(InterruptedException e){
                               }
                          partInspect.inspectVec();
                          }//end while
                          
                          p.setT2Done(true);
                     }//end run     
                Here is the change method (thread 1):
                public void changeVec(String s){
                           accessLock.lock();
                           try{
                                while (!editable)
                                     canWrite.await();
                           /* Parse the String, this is okay so I took out code that wasn't really needed */     
                
                                        if (changeType.equals("delete")){
                                             /* retrieve the object and send it to delete method */
                                             System.out.println("Thread One says " + partID + " was DELETED from the Part Vector");
                                             delPart(newPart);
                                        }                                                                          
                                        if (changeType.equals("add")){ 
                                             /*Parse the rest of the line, create new part object */
                                             System.out.println("Thread One says " + partName + " was ADDED to the Part Collection");
                                             addPart(newPart);                    
                                        }//end else if          
                                }//end while tokens.           
                                editable = false;
                                canRead.signal();     
                           }//end try
                           catch(InterruptedException e){      }
                           finally{
                                accessLock.unlock();
                           }
                      }//end changeVec          
                Here is the Inspect method (thread 2):
                public void inspectVec(){
                           accessLock.lock();           
                           try{           
                                while (editable)
                                     canRead.await();
                                     
                                editable = true;
                                 
                               /* a bunch of s.o.p to display message */     
                      
                              count++;
                              canWrite.signal();                
                           }//end try     
                           catch(InterruptedException e){           }
                           finally{
                                accessLock.unlock();
                           }          
                      }//end inspectVec
                • 5. Re: Thread Synchronization
                  800298
                  Not sure, but I think this happens because thread 1 continues after signalling thread 2 and it doesn't reach the next await method unless there is good input. So it continues and prints those exception messages but when the good input arrives it reaches await and waits for thread 2 to signal it. Make sense?
                  • 6. Re: Thread Synchronization
                    807589
                    Yes, that does make sense. Do you have any recommendations as to how to fix it easily?
                    • 7. Re: Thread Synchronization
                      800298
                      This is one way of doing it:
                      await write lock
                      do 
                          get input
                      until input == good
                      write
                      signal read
                      • 8. Re: Thread Synchronization
                        807589
                        The change method only receives a valid line to parse....The parsing in the run method of thread one will only send a valid string to the change method, so I guess that is why I am not sure where the problem is. Wouldn't I need to change the code in the run method?
                        • 9. Re: Thread Synchronization
                          800298
                          Ok, how about you just bung in a Thread.yield() after the read signal and see if that helps! ;)
                          • 10. Re: Thread Synchronization
                            807589
                            I tried adding Thread.yield() after the canRead.signal() in the change method and I got the same output as before
                            • 11. Re: Thread Synchronization
                              807589
                              I'm still not sure I understand why you are using threads for this.

                              The whole point of threading is to allow two processes to act simultaneously. Just because it fits the producer-consumer model doesn't mean that it's appropriate.

                              The algorithm you're describing is like:
                              A = producer, B = consumer
                              1. A.produce(a)
                              2. B.consume(a)
                              3. A.produce(b)
                              4. B.consume(b)
                              5. A.produce(c)
                              6. B.consume(c)

                              At no point are you doing two things at once, so there's no reason to thread.

                              You may think that you're gaining by doing something like this:
                              A = producer, B = consumer
                              1. A.produce(a)
                              2. A.produce(b), B.consume(a)
                              3. A.produce(c), B.consume(b)
                              4. B.consume(c)

                              But this is done in the first example by pipelining, probably more consistently than threading would allow.

                              A proper producer consumer model usually involves an imbalance between the time it takes to produce and the time it takes to consume. For example, if it takes a long time to produce but only a little while to consume, it would look more like this:
                              A = producer, B = producer, C = producer, D = consumer
                              1. A.produce(a), B.produce(b), C.produce(c)
                              2. A.produce(d), D.consume(a), B still producing b, C still producing c
                              3. B.produce(e), D.consume(b), A still producing d, C still producing c
                              4. C.produce(f), D.consume(c), A still producing d, B still producing e
                              • 12. Re: Thread Synchronization
                                800298
                                Imagist wrote:
                                I'm still not sure I understand why you are using threads for this.

                                The whole point of threading is to allow two processes to act simultaneously. Just because it fits the producer-consumer model doesn't mean that it's appropriate.
                                Isn't the idea here that the producer thread can continue parsing the input while the consumer is doing its thing? There is a real concurrency benefit there.

                                That's why I think the output of the program is in fact already correct and the OP shouldn't fix it in the way that I tentatively described.
                                • 13. Re: Thread Synchronization
                                  807589
                                  In a single thread, this would be handled by pipelining (assuming his processor was made after 1980). Using concurrency will probably only interfere with the processor pipelining effectively.

                                  At least, that's my perception. It's difficult to predict how high-level objects will behave at a low level.
                                  • 14. Re: Thread Synchronization
                                    807589
                                    Yes, I would agree. You don't necessarily need two threads to do this, but we are supposed to be applying the producer/consumer problem with thread synchronization.

                                    To this point, my threads are synchronized. If I comment out those exception print lines in my run method, my program does exactly what it is supposed to do and looks exactly like it is supposed to.
                                    1 2 Previous Next