2017-03-14 57 views
0

我是Java編程新手。我想用wait()和notify()來運行兩個線程。但我不能使用線程同步,睡眠,良率或等待(參數)任務標誌。我寫了它,但我不得不使用睡眠。有人可以幫助我改變它沒有睡眠。 這是我的主類Java - 兩個線程wait()和notify()

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."); 
     }   
    } 

這是我的第二個類。

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(); 
    } 
} 
} 

這是我的輸出。

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. 

謝謝。我的英語不好。對不起。

+0

如果您沒有等待的線程通知它會丟失。在進行狀態更改後需要通知,那麼您需要在wait()的循環中檢查狀態更改,因爲它可能會虛假地喚醒。 –

+0

這裏記錄了正確使用'wait()'和'notify()'。 https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html –

+0

你想要/期望輸出看起來像什麼? –

回答

0

在mainClass中創建了100次兩個線程,我認爲你應該只創建兩個線程,並在這兩個線程中循環運行100次。

也許你需要做這樣的事情...

  1. 生產企業應共同創造100任務(一次一個),並待興,爲消費者每個任務後。
  2. 消費者應該等待任務,並在完成當前任務時通知生產者,他們等待下一個任務。

所以你的mainClass應該看起來像這樣,循環應該在producer()和consumer()方法中。

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."); 
} 

} 

和處理器也許這樣的事情...

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); 
    } 
} 
} 

通常有一個隊列,而不是taskNo變量,其中生產者把任務和消費者在需要的任務。但在你的情況一次只能有一個任務,因爲生產者應該等待消費者完成。所以你可以使用一個簡單的變量(taskNo)而不是一個隊列。

1

提示:

  1. 的正確使用wait涉及等待具體的事情發生。正確執行是這樣的

    synchronize (x) { 
        while (!x.itHasHappened()) { 
         x.wait(); // for it to happen 
        } 
    } 
    

    環路是必要的,因爲它可以得到一個基本鎖定虛假通知。

  2. 在您的具體示例中,問問自己什麼必須等待發生什麼。我認爲你錯了。 produce(N)究竟等什麼,爲什麼?

相關問題