プログラミングの練習用に人生ゲームを書いています。ジェネレーターには 3 つの異なる実装があります。1 つ目: 1 つのメイン スレッド + N 個のサブ スレッド、2 つ目: SwingWorker + N 個のサブ スレッド、3 つ目: SwingWorker + ExecutorService。N は、使用可能なプロセッサーまたはユーザー定義の数です。最初の 2 つの実装は、1 つ以上のスレッドで正常に動作します。ExecutorServise を使用した実装は、1 つのスレッドで正常に実行されますが、複数のスレッドでロックされます。私はすべてを試しましたが、解決策を得ることができません。
ここで、うまく機能する実装のコード(2番目のもの):
package example.generator;
import javax.swing.SwingWorker;
/**
* AbstractGenerator implementation 2: SwingWorker + sub threads.
*
* @author Dima
*/
public final class WorldGenerator2 extends AbstractGenerator {
/**
* Constructor.
* @param gamePanel The game panel
*/
public WorldGenerator2() {
super();
}
/* (non-Javadoc)
* @see main.generator.AbstractGenerator#startGenerationProcess()
*/
@Override
protected void startGenerationProcess() {
final SwingWorker<Void, Void> worker = this.createWorker();
worker.execute();
}
/**
* Creates a swing worker for the generation process.
* @return The swing worker
*/
private SwingWorker<Void, Void> createWorker() {
return new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws InterruptedException {
WorldGenerator2.this.generationProcessing();
return null;
}
};
}
/* (non-Javadoc)
* @see main.generator.AbstractGenerator#startFirstStep()
*/
@Override
public void startFirstStep() throws InterruptedException {
this.getQueue().addAll(this.getLivingCells());
for (int i = 0; i < this.getCoresToUse(); i++) {
final Thread thread = new Thread() {
@Override
public void run() {
WorldGenerator2.this.fistStepProcessing();
}
};
thread.start();
thread.join();
}
}
/* (non-Javadoc)
* @see main.generator.AbstractGenerator#startSecondStep()
*/
@Override
protected void startSecondStep() throws InterruptedException {
this.getQueue().addAll(this.getCellsToCheck());
for (int i = 0; i < this.getCoresToUse(); i++) {
final Thread thread = new Thread() {
@Override
public void run() {
WorldGenerator2.this.secondStepProcessing();
}
};
thread.start();
thread.join();
}
}
}
以下は、エグゼキュータ サービスで動作しない実装のコードです。
package example.generator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.SwingWorker;
/**
* AbstractGenerator implementation 3: SwingWorker + ExecutorService.
*
* @author Dima
*/
public final class WorldGenerator3 extends AbstractGenerator {
private CountDownLatch countDownLatch;
private ExecutorService executor;
/**
* Constructor.
* @param gamePanel The game panel
*/
public WorldGenerator3() {
super();
}
/* (non-Javadoc)
* @see main.generator.AbstractGenerator#startGenerationProcess()
*/
@Override
protected void startGenerationProcess() {
this.executor = Executors.newFixedThreadPool(this.getCoresToUse());
final SwingWorker<Void, Void> worker = this.createWorker();
worker.execute();
}
/**
* Creates a swing worker for the generation process.
* @return The swing worker
*/
private SwingWorker<Void, Void> createWorker() {
return new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws InterruptedException {
WorldGenerator3.this.generationProcessing();
return null;
}
};
}
/* (non-Javadoc)
* @see main.generator.AbstractGenerator#startFirstStep()
*/
@Override
public void startFirstStep() throws InterruptedException {
this.getQueue().addAll(this.getLivingCells());
this.countDownLatch = new CountDownLatch(this.getCoresToUse());
for (int i = 0; i < this.getCoresToUse(); i++) {
this.executor.execute(new Runnable() {
@Override
public void run() {
WorldGenerator3.this.fistStepProcessing();
WorldGenerator3.this.countDownLatch.countDown();
}
});
}
this.countDownLatch.await();
}
/* (non-Javadoc)
* @see main.generator.AbstractGenerator#startSecondStep()
*/
@Override
protected void startSecondStep() throws InterruptedException {
this.getQueue().addAll(this.getCellsToCheck());
this.countDownLatch = new CountDownLatch(this.getCoresToUse());
for (int i = 0; i < this.getCoresToUse(); i++) {
this.executor.execute(new Runnable() {
@Override
public void run() {
WorldGenerator3.this.secondStepProcessing();
WorldGenerator3.this.countDownLatch.countDown();
}
});
}
this.countDownLatch.await();
}
}
ここで、私のアプリケーションのサンプルを小さなランチャーでダウンロードできます。コンソールに反復の結果のみを出力します:リンク
今私のコードは次のようになります:
/* (non-Javadoc)
* @see main.generator.AbstractGenerator#startFirstStep()
*/
@Override
public void startFirstStep() throws InterruptedException {
this.getQueue().addAll(this.getLivingCells());
final ArrayList<Callable<Void>> list = new ArrayList<Callable<Void>>(this.getCoresToUse());
for (int i = 0; i < this.getCoresToUse(); i++) {
list.add(new Callable<Void>() {
@Override
public Void call() throws Exception {
WorldGenerator3.this.fistStepProcessing();
return null;
}
}
);
}
this.executor.invokeAll(list);
}
しかし、ここでまた同じ問題が発生します。1 つのコア (スレッド) で実行しても問題はありません。コアの数を複数に設定すると、ロックされます。私の最初の質問には、(Eclipseで)実行できる例へのリンクがあります。多分私は前のコードで何かを見落としています。