2

私はスレッドを使用するのは初めてで、物事を理解しようとしているだけです。私の最終的なゲームはURLのリストを作成することです。私のプログラムは、リストから一度に1つのURLを取得し、そのURLを使用してアクションを実行します。多くのURLがあり、一部のスレッドが同じリストを使用しているときに、このリストが追加される可能性があります。

実験と学習を開始するために、数値で満たされた単純なArrayListを使用し、スレッドプールを使用してURLを取得しています。これが私のコードです:

public static void main(String[] args) {

    for (int i = 0; i < 200; i++){
        test.add(i);
    }

    SlothTest runner = new SlothTest();
    Thread alpha = new Thread(runner);
    Thread beta = new Thread(runner);

    ExecutorService tasker = Executors.newFixedThreadPool(10);

    while (!listEmpty()){
        tasker.submit(new SlothTest());
    }

    tasker.shutdown();
    System.out.println("Complete...");
}

@Override
public void run() {
    getLink();
    try {
        Thread.sleep(20);
    } catch (InterruptedException e) {
    }
}

private synchronized String getLink(){
    link = Thread.currentThread().getName() + " printed " + test.indexOf(test.size()-1);
    test.remove(test.size()-1);
    System.out.println(link);
    return link;
}

private synchronized static boolean listEmpty(){
    if (test.size() > 0){
        return false;
    } else {
        return true;
    }
}

プログラムを実行し、出力に-1を取得しているときに、いくつかの同時実行の問題が発生しています。なぜこれが起こっているのかわかりません。上記のコードは大雑把ですが、私は実際にマルチスレッドアプリの学習段階にあります。誰かが最初に私の並行性の問題を修正するのを手伝ってくれますか?それからあなたが私の上記のコードについてのポインタを私に与えることができればそれも素晴らしいでしょう

4

3 に答える 3

3

1つの問題はそれです

while (!listEmpty()){
    tasker.submit(new SlothTest());
}

アトミックではありません。したがってlistEmpty、falseを返す可能性がありますが、次のステートメントに到達するまでにtrueになります。

もう1つは、2つの異なるモニターで同期することです。

private synchronized String getLink(){ //synchronized on this

private synchronized static boolean listEmpty(){//synchronized on this.class

達成しようとしていることに役立つ方法があるリストの代わりに使用するBlockingQueueことを検討しましたか。

于 2012-09-11T15:30:10.983 に答える
2

グローバルに同期していません。メソッドを使用synchronizedすることで、タスクごとに異なる現在のインスタンスをロックします。代わりにグローバルロックを使用する必要があります。

final static Object globalLock = new Object();

private String getLink() {
   synchronized (globalLock) {
      link = Thread.currentThread().getName() + " printed " + test.indexOf(test.size()-1);
      test.remove(test.size()-1);                    
   }
   System.out.println(link);
   return link;
}

private boolean listEmpty(){
    synchronized (globalLock) {
       if (test.size() > 0){
          return false;
       } else {
          return true;
       }
    }
}
于 2012-09-11T15:29:07.693 に答える
2

URLのリストにConcurrentLinkedQueueを使用してみてください。これは、あなたの例と同様に、生産者/消費者の例でよく使用される優れた実装です(ただし、アクティブな「プロデューサー」自体はありません)。

于 2012-09-11T15:30:09.283 に答える