3

forループを介してfloat [12000]を12000回初期化する必要があります。次に、配列をスキャンして、特定のしきい値を超える値を探します。値がしきい値を超えた場合、特定のオブジェクトのインスタンス変数を操作します。

例:

Random random = new Random();
float[] x = new float[12000];

for (int i = 0; i < x.length; i++) {
  x[i] = random.nextFloat();
}

for (int i = 0; i < x.length; i++) {
  if (x[i] >= 0.75) {
  \\ do something interesting
  }
}

基本的に、配列の値を変更し、長さ 12000 の新しい配列でこれを 12000 回行う必要があります。「何か興味深い」コードは、別のデータ構造でそのインデックスを検索し、セッターを呼び出すだけです。システム時間の計算から、約 13 時間かかるはずです。私のマシンには 8 つのプロセッサーがあります。

Java のマルチスレッド機能を利用するにはどうすればよいですか? 特に、配列の初期化とスキャンを分割するスレッド ソリューションを探しています。スレッドを使用したソース コードを歓迎します。

4

1 に答える 1

8

これを8つの異なるスレッドに分割して、次のようなことを行うことができます

public class Worker implements Runnable {
    final private int minIndex; // first index, inclusive
    final private int maxIndex; // last index, exclusive
    final private float[] data;

    public Worker(int minIndex, int maxIndex, float[] data) {
        this.minIndex = minIndex;
        this.maxIndex = maxIndex;
        this.data = data;
    }

    public void run() {
        for(int i = minIndex; i < maxIndex; i++) {
            if(data[i] >= 0.75) {
                // do something interesting
            }
        }
    }
}


// *** Main Thread ***
float[] data = new float[12000];
int increment = data.length / 8;
for(int i = 0; i < 8; i++) {
    new Thread(new Worker(i * increment, (i + 1) * increment, data)).start();
}

これにより、配列が 8 つの異なるスレッドに分割されます。または、別のオプションは次のとおりです。

public class Worker implements Runnable {
    final private BlockingQueue<Integer> queue;
    final private float[] data;

    public Worker(BlockingQueue<Integer> queue) {
        this.queue = queue;
        this.data = data;
    }

    public void run() {
        while(true) {
            int i = queue.take();
            float f = data[i];
            // do something interesting to f
        }
    }
}


// *** Main Thread ***
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
float[] data = new float[12000];
for(int i = 0; i < 8; i++) {
    new Thread(new Worker(queue, data)).start();
}
for(int i = 0; i < data.length; i++) {
    if (data[i] >= 0.75) {
        queue.offer(i);
    }
}

これは、1 つのスレッドを使用して配列を反復処理し、興味深い数値を見つけてから、8 つのワーカー スレッドを使用して、興味深い数値に対して興味深い処理を行います。私はこのアプローチを好む傾向があります。最初のアプローチでは、1 つのワーカー スレッドが 1000 の興味深い数字を処理しなければならなくなり、別のワーカー スレッドはいくつかの興味深い数字を処理するだけで済む可能性があるからです。このアプローチにより、各スレッドがほぼ同じ量の興味深い数値を処理する必要があることが保証されます。

Executorの使用方法やワーカー スレッドのシャットダウン方法など、多くのことを省略しています。これに関するチュートリアルです

編集コードを取得して 8 つのスレッドで 12000 回実行するには、次のようにします。

public class Worker implements Runnable {
    private final int numberOfIterations;
    private final float[] x = new float[12000];

    public Worker(int numberOfIterations) {
        this.numberOfIterations = numberOfIterations;
    }

    public void run() {
        for(int i = 0; i < numberOfIterations; i++) {
            Random random = new Random();

            for (int i = 0; i < x.length; i++) {
                x[i] = random.nextFloat();
            }

            for (int i = 0; i < x.length; i++) {
                if (x[i] >= 0.75) {
                    \\ do something interesting
                }
            }
        }
    }
}


// *** Main Thread ***
Thread[] threads = new Thread[8];
for(int i = 0; i < 8; i++) {
    threads[i] = new Thread(new Worker(12000/8));
    threads[i].start();
}
for(int i = 0; i < 8; i++) {
    threads[i].join();
}

8 つのスレッドのそれぞれが、「float 配列の初期化、float 配列の反復」コードの 1500 回の反復を実行します。その後join、メソッドはスレッドが終了するまで待機します。のコード// do something interestingがスレッドセーフであることを確認してください-セッターを呼び出していると言ったので、複数のスレッドが同じセッターを呼び出さないこと、またはセッターが同期されていることを確認してください。AtomicIntegerセッターでのようなものを使用します。疑問がある場合は、setter コードを投稿してください。

于 2013-07-11T03:40:30.457 に答える