// ThreadExample2
// burton rosenberg
// july 9 ,1997


public class ThreadExample2 {

     public static void main(String [] args) {
         Message m = new Message() ;
         Producer p = new Producer(m) ;
         Consumer c = new Consumer(m) ;
         System.out.println("main: starting consumer") ;
         (new Thread(c)).start() ;
         System.out.println("main: starting producer") ;
         (new Thread(p)).start() ;
         System.out.println("main: exiting") ;
     }

}


class Producer implements Runnable {

     Message m ;
     int count = 0 ;

     Producer(Message m) { this.m = m ; }

     public void run() {
        System.out.println("producer: entered") ;
        while ( count < 100 ) {

           if ( ! m.getFlag() ) {
              // produce data
              m.data = "The count is " + count ;
              // flag that data is ready
              m.setFlag(true) ;
              count ++ ;
           }

           Thread.yield() ; // give other thread time on the CPU
        }
        System.out.println("producer: exit") ;
     }

}  

class Consumer implements Runnable {

     Message m ;

     Consumer(Message m) { this.m = m ; }

     public void run() {
        System.out.println("consumer: entered") ;
        while ( true ) {

           if ( m.getFlag() ) {
              // consume data
              System.out.println(m.data) ;
              // flag that data is "used"
              m.setFlag(false) ;
           }

           Thread.yield() ; // give other thread time on the CPU
        }
        // System.out.println("consumer: exit") ; // unreachable
     }
}

     
class Message {

    private boolean flag = false ;
    String data = "" ;

    synchronized boolean getFlag() {
        return flag ;
    }

    synchronized void setFlag(boolean b) {
        flag = b ;
    }

}
