2017-11-22 9 views
1

からhttp://www.siddhartha.ac.in/downloads/JP_Lab_Record2.pdfforループのすべての反復でスレッドを再利用できますか?

3スレッドの を持つマルチスレッドアプリケーションを実装するJavaプログラムを作成します。最初のスレッドは、毎秒 のランダムな整数を生成し、値が偶数の場合、2番目のスレッドは の2乗を計算して出力します。値が奇数の場合、3番目のスレッドは数字のキューブの値 を出力します。 main方法において

import java.util.*; 
class even implements Runnable 
{ 
    public int x; 
    public even(int x) 
    { 
     this.x = x; 
    } 
    public void run() 
    { 
     System.out.println("New Thread "+ x +" is EVEN and Square of " + x + " is: " + x * x); 
    } 
} 
class odd implements Runnable 
{ 
    public int x; 
    public odd(int x) 
    { 
     this.x = x; 
    } 
    public void run() 
    { 
     System.out.println("New Thread "+ x +" is ODD and Cube of " + x + " is: " + x * x * x); 
    } 
} 
class A extends Thread 
{ 
    public void run() 
    { 
     int num = 0; 
     Random r = new Random(); 
     try 
      { 
       for (int i = 0; i < 5; i++) 
        { 
         num = r.nextInt(100); 
         System.out.println("Main Thread and Generated Number is " + num); 
         if (num % 2 == 0) 
          { 
           Thread t1 = new Thread(new even(num)); 
       t1.start(); 
          } else { 
          Thread t2 = new Thread(new odd(num)); 
          t2.start(); 
      } 
         Thread.sleep(1000); 
      System.out.println("--------------------------------------"); 
        } 
      } 
     catch (Exception ex) 
      { 
       System.out.println(ex.getMessage()); 
      } 
    } 
} 
public class JavaProgram5 
{ 
    public static void main(String[] args) 
    { 
     A a = new A(); 
     a.start(); 
    } 
} 

は、forループの各反復のために、二つの新しいスレッドが作成されます。 forループのすべての反復で2つのスレッドを再利用することは可能ですか?

ありがとうございました。

+0

なぜを再利用使用複数のスレッドでこれをやっていますか?あなたは、多くの同期問題に遭遇する可能性が高いです。なぜ、1つのスレッドに値を印刷させるだけではないのですか? – FredK

+1

@FredK同期の問題を作成するために設計された割り当てのように聞こえます –

+1

@John割り当てられましたが、私は割り当てを超えて考えています。 – Ben

答えて

1

スレッドは、あなたが考えている方法で再利用することはできません。あなたが何をしているのかは、実際に番号を生成するたびに新しいスレッドを開始することです。その時点では、計算のためのスレッドをまったく持たないこともあります。

質問のサブテキストは、常に3つのスレッドが実行中であることを示しているようです。それはあなたの問題を本質的に2つの消費者の状況を持つ生産者にします。唯一の捉え方は、消費者が知的に行動し、必要なデータだけを取り上げなければならないということです。

ジェネレータコードは処理コードと同様に正しいトラックでオフになっています。主な変更点は、新しいスレッドを開始する代わりに、notify(実際にはnotifyAll)のスレッドがEvenOddのスレッドを実行する必要があることです。

毎秒1つのアイテムが生成されるので、実際には適切なキューは必要ありません。単一のIntegerオブジェクトは、消費されていない番号を保持するのに十分です。比較的古いアーキテクチャーでも処理に1秒以上かかる場合は、他の問題があります。 intの代わりにIntegerを使用する理由は、待機中のスレッドにオブジェクトが既に消費されていることを伝える必要があるからです。この場合、返すnullはかなり簡単な方法のようです。

class Producer implements Runnable, IntConsumer 
{ 
    private Integer buffer = null; 

    public void run() 
    { 
     new Random().ints().forEach(this); 
    } 

    public void accept(int i) 
    { 
     synchronized(this) { 
      this.buffer = i; 
      this.notifyAll(); 
     } 
     try { 
      Thread.sleep(1000L); 
     } catch(InterruptedException ie) { 
      throw new RuntimeException("Producer interrupted!"); 
     } 
    } 

    public Integer peek() 
    { 
     return this.buffer; 
    } 

    public synchronized Integer get() 
    { 
     Integer i = peek(); 
     this.buffer = null; 
     return i; 
    } 
} 

生成される整数をpeekgetを介してアクセスすることができるフィールドに配置されることに注意してください。生成コードは、バッファをクリアするgetと同様に、プロデューサオブジェクトをロックします。これにより、一度に1つのエンティティのみが値を変更できるようになります。

通常、コンシューマとプロデューサは、共有スタックやキューオブジェクトなどを介して通信します。同期は、LinkedBlockingQueueまたはArrayBlockingQueueのように、キューによっても行われます。この単純なケースでは、プロデューサはキュー機能を実装しているため、コンシューマはプロデューサを認識する必要があります。

コンシューマスレッドには、多くの共通機能があります。彼らはどちらもプロデューサの通知を待つ必要があり、ロックを取得し、次のオブジェクトが消費されていないかどうかをチェックし、それらに属しているかどうかを確認してから、消費するか待機します。エラーを回避するには、check-then-get操作全体をアトミックにする必要があることに注意してください。これらはすべて基本クラスで簡単にエンコードできます。このクラスは、番号を確認し、処理するための抽象メソッドがあります:

public abstract class Consumer implements Runnable 
{ 
    private final Producer producer; 

    public Consumer(Producer producer) 
    { 
     this.producer = producer; 
    } 

    public void run() 
    { 
     while(true) { 
      synchronized(this.producer) { 
       Integer i = this.producer.peek(); 
       if(i != null && check(i)) { 
        this.producer.get(); 
        process(i); 
       } 
       try { 
        this.producer.wait(); 
       } catch(InterruptedException ie) { 
        throw new RuntimeException("Consumer interrupted!"); 
       } 
      } 
     } 
    } 

    public abstract boolean check(int i); 

    public abstract void process(int i); 
} 

を具体的な実装は数入力のパリティかどうかを確認し、それらが適しているという数字を処理します。 checkprocessIntegerの代わりにintを受け入れることに注意してください。プロデューサが空であるかどうかを確認する責任はないことを強調してください。あなたが早期に終了するメインスレッドで問題が発生した場合は力mainを待つために、

public class Driver 
{ 
    public static void main(String[] args) 
    { 
     Producer prod = new Producer(); 
     new Thread(new Even(prod)).start(); 
     new Thread(new Odd(prod)).start(); 
     new Thread(prod).start(); 
    } 
} 

:最後に、ドライバーはこのすべてを結びつけるmain方法を含む

public class Even extends Consumer 
{ 
    public Even(Producer producer) 
    { 
     super(producer); 
    } 

    public boolean check(int i) 
    { 
     return (i % 2) == 0; 
    } 

    public void process(int i) 
    { 
     System.out.println("x=" + i + "; x^2=" + (i * i)); 
    } 
} 

public class Odd extends Consumer 
{ 
    public Odd(Producer producer) 
    { 
     super(producer); 
    } 

    public boolean check(int i) 
    { 
     return (i % 2) != 0; 
    } 

    public void process(int i) 
    { 
     System.out.println("x=" + i + "; x^3=" + (i * i * i)); 
    } 
} 

プロデューサーが次のようなもので終わる(永遠に):

Thread t = new Thread(prod); 
t.start(); 
t.join(); 

あなたは(少なくともLinux上)Ctrl+Cを押すまでのコードは、1秒に1回、次のような出力を生成します:

x=966307133; x^3=-1676528219 
x=1271569805; x^3=-1481001707 
x=456385150; x^2=-1701399036 
x=-474801821; x^3=-813682373 
x=-1046547765; x^3=927976307 
x=-148577454; x^2=-185956796 
x=-14905035; x^3=-1126539123 
x=2071820769; x^3=-1426032223 
x=1075272421; x^3=1952259101 
x=-895041093; x^3=-978791741 
x=-2054472224; x^2=3441664 
... 
0

はfixedThreadのpool.itスレッド

  import java.util.Random; 
      import java.util.concurrent.ExecutorService; 
      import java.util.concurrent.Executors; 
      import java.util.concurrent.TimeUnit; 


      public class MainClass { 

       public static void main(String[] args){ 


         A a = new A(); 
         a.start(); 

       } 

      } 

      class A extends Thread 
      { 
       public void run() 
       { 

        ExecutorService executorService = Executors.newFixedThreadPool(2); 
        int num = 0; 
        Random r = new Random(); 
        try 
         { 
          for (int i = 0; i < 5; i++) 
           { 
            num = r.nextInt(100); 
            System.out.println("Main Thread and Generated Number is " + num); 
            if (num % 2 == 0) 
             { 
             executorService.submit(new even(num)); 

             } else { 
              executorService.submit(new odd(num)); 

         } 
            Thread.sleep(1000); 
         System.out.println("--------------------------------------"); 
           } 
         } 
        catch (Exception ex) 
         { 
          System.out.println(ex.getMessage()); 
         } 
       finally { 
        executorService.shutdown(); 
       } 
       try { 
        executorService.awaitTermination(1, TimeUnit.HOURS); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       } 
      } 

      class even implements Runnable 
      { 
       public int x; 
       public even(int x) 
       { 
        this.x = x; 
       } 
       public void run() 
       { 
        System.out.println("New Thread "+ x +" is EVEN and Square of " + x + " is: " + x * x); 
       } 
      } 
      class odd implements Runnable 
      { 
       public int x; 
       public odd(int x) 
       { 
        this.x = x; 
       } 
       public void run() 
       { 
        System.out.println("New Thread "+ x +" is ODD and 
       Cube of " + x + " is: " + x * x * x); 
       } 
      } 
関連する問題