2017-03-14 15 views
0

Javaプログラミングには初めてです。私はwait()とnotify()を使って2つのスレッドを実行したい。しかし、私はスレッドの同期、スリープ、歩留まりまたは待機(パラメータ)のタスクフラグを使用することはできません。私はそれを書いたが、私は睡眠を使用しなければならなかった。誰かが私にそれを睡眠なしに変えるのを助けることができますか? これは私のメインクラスですJava - wait()とnotify()を持つ2つのスレッド

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

これは私の2番目のクラスです。

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では2回のスレッドを100回作成しましたが、2つのスレッドのみを作成し、その2つのスレッドでループを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変数のキューがあります。しかし、中あなたのケースでは、プロデューサはコンシューマが完了するのを待つ必要があるため、キューは一度に1つのタスクしか持てません。したがって、キューの代わりに単純な変数(taskNo)を使用することができます。

1

ヒント:

  1. waitの正しい使用が起こることを特定の何かを待っているが含まれます。正しい実装は、原始的なロックに偽の通知を取得することが可能であるため、ループが必要である。この

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

    のようなものです。

  2. 具体的な例では、何が起こるのを待たなければならないか自問自答してください。私はあなたが間違っていると思う。実際にはproduce(N)は何を待っていますか?なぜですか?

関連する問題