0

わかった。3 つのスレッドを作成する必要があります。1 つは奇数を取得するスレッド、もう 1 つは偶数を取得するスレッド、もう 1 つは奇数と偶数を加算するスレッドです。出力は次のようになります (1,2,3,3,4,7...)。私はスレッドが初めてで、スレッドがどのように機能するかについてまだ不安定ですが、これは私がこれまでに持っているものです:

class even extends Thread 
{
    public void even()
    {
        Thread ThreadEven = new Thread(this); 
        start(); 
    } 
    public void run() 
    {
        try
        {
            for(int i = 0; i < 10; i += 2) 
            {
                System.out.println(i);
            }
            Thread.sleep(1000);
        }
        catch(Exception e) 
        {
            System.out.println("Error: Thread Interrupted");
        } 
    } 
}

class odd extends Thread 
{ 
    public void odd() 
    {
        Thread ThreadOdd = new Thread(this); 
        start(); 
    } 
    public void run() 
    {
        try
        {
            for(int i = 1;i < 10; i += 2) 
            System.out.println(i);
            Thread.sleep(1000);
        }
        catch(Exception e) 
        {
            System.out.println("Error: Thread Interrupted");
        } 
    } 
}
class ThreadEvenOdd
{
    public static void main(String args []) 
    {
        even e = new even();
        odd o = new odd();

    } 
} 

これは 0,2,4...そして 1,3,5 を出力します。インターリーブする方法は?そして、私が望むものをインターリーブしていますか?スレッドも同期する必要がありますか? 私が理解していないのは、奇数スレッドと偶数スレッドの値を 3 分の 1 にして合計を加算する方法です。コードのフォーマットが正しくない場合は、あらかじめお詫び申し上げます。

4

2 に答える 2

1

前述のように、これは一種の高度な問題であり、これを試す前に多くのチュートリアルを読む必要があります。この短いプログラムでさえ、実際にJavaの並行性について熟考することにかなりの時間を費やしていなければ、それを書くことはできなかったでしょう。(ヒント-本を購入してください。すべてそこにあります。)

クラスの偶数と奇数はプロデューサーです。クラスの合計は消費者です。プロデューサーとコンシューマーは、データを渡すためにブロッキングキューを共有します。生産者は負の数を毒薬として使用して、それらが終了し、これ以上のデータがないことを示します。消費者が毒薬を検出すると、countDownラッチをデクリメントします。メインスレッドは、これを作業が完了したことを示すシグナルとして使用します。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;


public class OddEven
{
   public static void main(String [] args) throws InterruptedException
   {
      BlockingQueue<Integer> evens = new ArrayBlockingQueue<Integer>(1);
      BlockingQueue<Integer> odds = new ArrayBlockingQueue<Integer>(1);
      even e = new even(evens);
      odd o = new odd(odds);
      sum s = new sum(evens, odds);

      e.start();
      o.start();
      s.start();
      s.waitUntilDone();
   }
}

class sum extends Thread
{
    private final BlockingQueue<Integer> in1;
    private final BlockingQueue<Integer> in2;

    private final CountDownLatch done = new CountDownLatch(1);
    public sum(BlockingQueue<Integer> in1, BlockingQueue<Integer> in2)
    {
        this.in1 = in1;
        this.in2 = in2;
    }

    public void waitUntilDone() throws InterruptedException
    {
       done.await();
    }
    public void run()
    {
        try
        {
           while (true)
           {
              int a = in1.take();
              int b = in2.take();
              if (a == -1 && b == -1)
                 break;

              int c = a + b;
              System.out.println(a);
              System.out.println(b);
              System.out.println(c);
           }
           done.countDown();
        }
        catch(Exception e)
        {
            System.out.println("Error: Thread Interrupted");
        }
    }
}

class even extends Thread
{
    private final BlockingQueue<Integer> out;

    public even(BlockingQueue<Integer> out)
    {
       this.out = out;
    }
    public void run()
    {
        try
        {
            for(int i = 0; i < 10; i += 2)
               out.put(i);

            out.put(-1);
        }
        catch(Exception e)
        {
            System.out.println("Error: Thread Interrupted");
        }
    }
}

class odd extends Thread
{
   private final BlockingQueue<Integer> out;

   public odd(BlockingQueue<Integer> out)
   {
      this.out = out;
   }
    public void run()
    {
        try
        {
            for(int i = 1;i < 10; i += 2)
               out.put(i);

           out.put(-1);
        }
        catch(Exception e)
        {
            System.out.println("Error: Thread Interrupted");
        }
    }
}

典型的な出力は次のとおりです。

0
1
1
2
3
5
4
5
9
6
7
13
8
9
17
Sums are complete
于 2012-10-06T03:42:53.360 に答える
0

プロデューサースレッド(偶数と奇数)から「コンシューマー」スレッドに数値を「渡す」方法が必要です。

「最も単純な」が最善の方法ではないのは、1 つのエントリを持つ可変配列です。同時スレッドがそれを破損するのを避けるために、何か (配列?) を同期/ロックする必要があります。

おそらく、より簡単で良い方法は、ArrayDeque などの「両端キュー」を使用することです。これにより、値を一方の端に入れ、もう一方の端から削除できます。ここでも、アクセスを同期する必要があります。

すべてのスレッドの外部にキューを作成し、それらを渡すか、または可視にします。

class Example {
    protected Deque<Integer> queueEven = new ArrayDeque<Integer>();
    protected Deque<Integer> queueOdd = new ArrayDeque<Integer>();
    // you can synchronize on some mutable flag to finish, too.

    class Even extends Thread {
        public void run() {
            for (int i = 0; i < 10; i += 2) {
                synchronized (queueEven) {
                    queueEven.add( i);
                }
            }
        } 
    } 

    class Odd extends Thread {
        public void run() {
            for (int i = 1; i < 10; i += 2) {
                synchronized (queueOdd) {
                    queueOdd.add( i);
                }
            }
        } 
    } 

    class AddEvenOdd extends Thread {
        public void run() {
             while (true) {
                 int even;
                 synchronized (queueEven) {
                     even = queueEven.removeFirst();
                 }
                 int odd;
                 synchronized (queueOdd) {
                     odd = queueOdd.removeFirst();
                 }
                 int result = even + odd;
                 System.out.println("result="+result);
             }
        }
    }
}
于 2012-10-06T03:52:59.697 に答える