HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

"Multi-Threading in Java"
Vol. 3, Issue 1, p. 72

	

Listing 1: Basic thread.java
 
import java.lang.*; 
import java.io.*; 
/* 
** Starts two threads which print messages asynchronously. 
*/ 
public class BasicThread 
{ 
   public static void main( String args[] ) throws IOException,InterruptedException 
   { 
      CountThread countThread1 = new CountThread( "Thread 1" ); 
      CountThread countThread2 = new CountThread( "Thread 2" ); 

      System.out.println( "Starting Threads" ); 
      countThread1.start();   // Starts thread and calls run method 
      countThread2.start();   // Starts thread and calls run method 
      System.out.println( "Threads Started" ); 

      countThread1.join();    // Wait for thread to end. 
      countThread2.join();    // Wait for thread to end. 
      System.out.println( "Threads Stopped" ); 

      System.out.println( "Press  to quit." ); 
      System.in.read();       // Wait for user to press enter       
   } 
} 

Listing 2: countthread.java
 
import java.lang.*; 

/* 
** This class prints messages to the system console.  Objects 
** of this class may be run as separate threads by calling 
** the thread method start(). 
*/ 
public class CountThread extends Thread 
{ 
   final int MAX_INDEX = 10; 
   protected String currentThreadName; 
     
   public CountThread( String threadName ) 
   { 
      currentThreadName = threadName; 
   } 
     
   public void run() 
   { 
      int index; 
         
      for( index = 0;  index < MAX_INDEX;  index += 1 ) 
      { 
         System.out.println( currentThreadName + ": " + index ); 
      } 
   } 
} 
  

Listing 3.
 
public void sem_wait( String currentThreadName ) 
{ 
 // Statements here are not run under protection of a monitor synchronized( this ) 
 { 
  // Statements here are under protection of the objectís monitor. 
  // Each instance of the object will only allow one thread at a time access to the method. 
 } 
 // Statements here are not run under protection of a monitor 
} 

Listing 4: Definition of blocked-set semaphore.
 
obj.sem_wait(): if( obj.s > 0 ) 
  obj.s = obj.s Ů 1; 
 else 
  obj.wait(); // Suspend 

obj.sem_signal(): if( thread suspended on this semaphore ) 
  notify(); // Awaken waiting thread 
 else 
  obj.s = obj.s + 1; 

Listing 5: Semaphore.java
 
/* 
** The class implements a blocked-set semaphore which can be used 
** for thread synchronization. 
**  
** A blocked-set semaphore has the following definition: 
** 
**    A single thread awakens one suspended thread. 
** 
**    obj.sem_wait(): if( obj.s > 0 ) 
**                       obj.s = obj.s - 1; 
**                      else 
**                         obj.wait();   // Suspend 
**  
**    obj.sem_signal(): if( thread suspended on this semaphore ) 
**                         notify();     // Awaken waiting thread 
**                      else 
**                         obj.s = obj.s + 1; 
*/ 
public class Semaphore 
{ 
   private int     s; 
   private int     numWait; 
   private String  currentSemaphoreName; 
   private boolean doDebug; 
     
     
   public Semaphore() 
   { 
      s = 0; 
      numWait = 0; 
      currentSemaphoreName = this.toString(); 
      doDebug = false; 
   } 
  

   public Semaphore( String name, int initial, boolean debug ) 
   { 
      s = initial; 
      numWait = 0; 
      currentSemaphoreName = name; 
      doDebug = debug; 
   } 
    
    
   public void sem_wait() 
   { 
      sem_wait( Thread.currentThread().getName() ); 
   } 
    
    
   public synchronized void sem_wait( String currentThreadName ) 
   { 
      boolean retry; 
       
      /* 
      ** Check to see if semaphore was signled while no thread was waiting. 
      */ 
      if( s > 0 ) 
      { 
        s = s - 1;   // Match up one signal with one wait 
        return; 
      } 
       
      numWait = numWait + 1;     // Mark the we are going to wait. 
      do 
      { 
         retry = false; 
         try 
         { 
            if( doDebug ) 
               System.out.println( currentThreadName + " Waiting for " + currentSemaphoreName ); 
                
            this.wait();   // Do a Java wait() mutex. 
             
            if( doDebug ) 
               System.out.println( currentThreadName + " Received " + currentSemaphoreName );             
                
         } catch( InterruptedException e ) { retry = true; }          
      } while( retry ); 
   } 
  

   public void sem_signal() 
   { 
      sem_signal( Thread.currentThread().getName() ); 
   } 
    
    
   public synchronized void sem_signal( String currentThreadName ) 
   { 
      boolean retry; 

      /* 
      ** Check to see if a thread is waiting for a signal. 
      ** If not, then remember that a signal was generated without 
      ** a wait. 
      */ 
      if( numWait == 0 ) 
      { 
        s = s + 1; 
        return; 
      } 
       
      numWait = numWait - 1;   // We are going to wake up one waiting thread. 
      do 
      { 
         retry = false; 
         try 
         {   
            if( doDebug ) 
               System.out.println( currentThreadName + " Notify for " + currentSemaphoreName ); 
                
            this.notify(); 
         } 
         catch( Exception e ) { retry = true; }          
      } while( retry ); 
   }    
} 

Listing 6: Producer.java
 
import java.lang.*; 
import java.math.*; 

public class Producer extends Thread 
{ 
   final int            MAX_PRODUCT_BUFF = 4; 
   volatile private int product[] = new int[MAX_PRODUCT_BUFF]; 
   volatile int         count;    
   int                  localCountIn; 
   int                  localCountOut; 
   int                  inIndex; 
   int                  outIndex; 
   volatile Semaphore   notFull  = new Semaphore( "notFull",  0, true ); 
   volatile Semaphore   notEmpty = new Semaphore( "notEmpty", 0, true ); 
     
     
   public Producer( String threadName ) 
   { 
      setName( threadName ); 
      count = 0; 
      inIndex = 0; 
      outIndex = 0; 
      localCountIn = 0; 
      localCountOut = 0; 
   } 
    
     
   public void run()  
   { 
      final int MAX_PRODUCTION = 10;  
      int index;        
         
      for( index = 0;  index < MAX_PRODUCTION;  index += 1 ) 
      { 
         make_product( index + 100 ); 
         System.out.println( getName() + ": " + (index + 100) );          
      } 
      make_product( 0 );  // Signal end of production 
      System.out.println( getName() + ": done" ); 
   } 
    
    
   public void make_product( int value ) 
   {   
      if( localCountIn  ==  MAX_PRODUCT_BUFF ) 
         notFull.sem_wait(); 
   
      product[inIndex] = value; 
      synchronized( this ) 
      { 
         count = count + 1; 
         localCountIn = count; 
      } 

      if( localCountIn == 1 ) 
         notEmpty.sem_signal(); 
               
      inIndex = (inIndex + 1); 
      if( inIndex == MAX_PRODUCT_BUFF ) 
        inIndex = 0; 
   } 
      
    
    
   public int take_product() 
   { 
      int value; 
       
      if( localCountOut == 0 ) 
         notEmpty.sem_wait( currentThread().getName() ); 
          
      value = product[outIndex]; 
      synchronized( this ) 
      { 
         count = count - 1; 
         localCountOut = count; 
      } 
          
      if( localCountOut  ==  MAX_PRODUCT_BUFF - 1 ) 
         notFull.sem_signal( currentThread().getName() );             
       
      outIndex = outIndex + 1; 
      if( outIndex  ==  MAX_PRODUCT_BUFF ) 
         outIndex = 0; 
          
      return( value ); 
   }    
} 
  

Listing 7: consumer.java
 
import java.lang.*; 

public class Consumer extends Thread 
{ 
   private Producer theProducer; 

   public Consumer( String threadName, Producer producer ) 
   { 
      setName( threadName ); 
      theProducer = producer; 
   } 

   public void run() 
   { 
      int index; 
      int value; 

      do 
      { 
         value = theProducer.take_product(); 
         if( value  !=  0 ) 
            System.out.println( getName() + ": " + value ); 
      } while( value  !=  0 ); 
      System.out.println( getName() + ": done" ); 
   } 
} 


 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.