Search code examples
javamultithreadingjava-threads

Java - two threads with wait() and notify()


I am new to Java programming. i want to run two threads using wait() and notify(). But I cant use task flags for thread synchronization,sleep, yield or wait(parameter).I wrote it, but i had to use sleep. can someone help me to change it to without sleep. This is my main class

public class mainClass{

       public static void main(String args[]) throws InterruptedException {

           final Processor processor = new Processor();

           for(int i=0; i<100; i++){

               final int z = i;
               Thread trainer = new Thread(new Runnable(){

                   public void run(){
                       try{
                           processor.produce(z);
                       }catch(InterruptedException e){
                           e.printStackTrace();
                       }
                   }           
               });

               Thread sportsman = new Thread(new Runnable(){

                   public void run(){
                       try{
                           processor.consume(z);
                       }catch(InterruptedException e){
                           e.printStackTrace();
                       }
                   }           
               });

               trainer.start();
               sportsman.start();

               trainer.join();
               sportsman.join();

           }
           System.out.println("100 Tasks are Finished.");
       }          
    }

this is my second class.

public class Processor {

public void produce(int n) throws InterruptedException {
    synchronized (this){
        System.out.println("Trainer making " + (n+1) + " Task..." );
        wait();
        System.out.println(""); 
    }
}

public void consume(int m) throws InterruptedException {
    Thread.sleep(1); 
    //I want to run the code without using sleep and get same output
    synchronized (this){
        System.out.println("Sportman doing " + (m+1) + " Task...");
        notify();
    }
}
}

this is my output.

Trainer making 1 Task...
Sportman doing 1 Task...

Trainer making 2 Task...
Sportman doing 2 Task...

.
.
.

Trainer making 99 Task...
Sportman doing 99 Task...

Trainer making 100 Task...
Sportman doing 100 Task...

100 Tasks are Finished.

thank you. my english is bad. sorry for it.


Solution

  • In mainClass you created 100 times two threads, I think you should create two threads only and in those two threads run the loop 100 times.

    Probably you needed to do something like this...

    1. The producer should create together 100 task (one at a time) and wait after each task for the consumer to be done.
    2. The consumer should wait for a task and notify the producer when finished with the current task, them wait for the next task.

    So your mainClass should look like this, loops should be in the producer() and consumer() methods.

    public class mainClass {
    
    public static void main(String args[]) throws InterruptedException {
    
        final Processor processor = new Processor();
    
        Thread trainer = new Thread(new Runnable() {
            public void run() {
                try {
                    processor.produce();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
        Thread sportsman = new Thread(new Runnable() {
            public void run() {
                try {
                    processor.consume();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
        trainer.start();
        sportsman.start();
    
        trainer.join();
        sportsman.join();
    
        System.out.println("100 Tasks are Finished."); 
    }
    
    }
    

    And the Processor maybe something like this...

    public class Processor {
    
    private int taskNo = 0; // the number of the current task
                            // (0 = there is no task, but will be)
                            // (-1 = there won't be more task)
    
    public void produce() throws InterruptedException {
        synchronized (this) {
            for (int i = 0; i < 100; i++) {
                taskNo = i + 1; // making a task number (i+1)
                System.out.println("Trainer making " + taskNo + " Task...");
                notify(); // notifies the consumer that the task was made
                wait(); // and waiting the consumer to finish... zzzz...
                System.out.println("");
            }
            taskNo = -1; // there will be no more task
            notify(); // notify the consumer about it
        }
    }
    
    public void consume() throws InterruptedException {
        synchronized (this) {
            do {
                if (taskNo == 0) {
                    wait(); // there is no task to do, waiting... zzzz...
                }
                if (taskNo != -1) {
                    System.out.println("Sportman doing " + taskNo + " Task...");
                    taskNo = 0; // sets the task to done
                    notify(); // notifies the producer that the task was done
                }
            } while (taskNo != -1);
        }
    }
    }
    

    Typically there is a queue instead of the taskNo variable, where the producer puts tasks and the consumer takes tasks from in. But in your case the queue can have only 1 task at a time, because the producer should wait for the consumer to finish. So you can use a simple variable (taskNo) instead of a queue.