2016-03-28 6 views
2

スレッドは別のクラスに基づいて他のスレッドによって作成された同じ変数を使用しているため、スレッドで作業していて問題があります。 問題は、このコードを使用することです:Javaで同じ変数を使用するスレッド

public void run() { 
    int cityID = 0; 
    int requestID = 0; 
    boolean inBase = true; 
    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    while (inBase == true) { 
     for (cityID = 0; cityID < world.getCities().size(); cityID++) { 
      if ((!world.getCities().get(cityID).getRequestsList().isEmpty()) && (inBase == true)) { 
       for (requestID = 0; requestID < world.getCities().get(cityID).getRequestsList() 
         .size(); requestID++) { 
        if (world.getCities().get(cityID).getRequestsList().get(requestID).isRequest() == true) { 
         world.getCities().get(cityID).getRequestsList().get(requestID).setRequest(false); 
         System.out.println(Thread.currentThread().getName() + " is flying to " 
           + world.getCities().get(cityID).getName()); 
         inBase = false; 
         break; 
        } 
       } 
      } 
     } 
    } 
} 

結果は次のとおりです。

City 859|342 is sending request for airplane. . . 
City 328|669 is sending request for airplane. . . 
City 718|287 is sending request for airplane. . . 
Airplane kS-2 is flying to City 859|342 
Airplane kS-1 is flying to City 859|342 

あなたは飛行機が同じ市に飛んでいるし、それは間違って見るように。私はすでに行っているので、 は条件

if world.getCities().get(cityID).getRequestsList().get(requestID).isRequest() == true) 

、私はこのような状況を防ぐために何をすべきか分からないのです。そして、私は偽

world.getCities().get(cityID).getRequestsList().get(requestID).setRequest(false); 

しかし、スレッドと同じ値を探しているのは、この値を変更します同時に、私ができることは、それぞれランダムな時間にスリープしてから、同じ時間に真の値をチェックすることはありませんが、無作為に私は2つの同じ値を得ることができるので、飛行機は同じターゲットに飛ぶことがあります。 私はそれを行うより良い方法があると思いますが、分かりません。助けてください。

答えて

0

私が見る方法は、あなたのリストには、スタックのように動作し、要求を飛び出してい代わりに

world.getCities().get(cityID).getRequestsList() 

をループで、あなたのすべてのスレッドがそう同時に同じ要求リストへのアクセスを得ることです一つずつ。このようにして、各ポップはあなたのスレッドに別の要求を与えます。

+1

新しい同期メソッドを作成することで簡単に簡単にできます。ありがとう:) – Vrangz

0

コードを少し整理しました。最初にスレッドを使用する理由は完全にはっきりしていません。メインスレッドであなたのリストをループし、平面オブジェクトを作成するだけで十分です。それらは例えばリストに格納することができる。飛行機をシミュレートするためにスレッドを使用したいと思うかもしれないと思いますか?それが事実であるとrunメソッドをしばらく(inBase)の後に終了していないなら、あなたは一度に一つだけのスレッドがあなたの世界を変更できることを確認したロックオブジェクトを使用する場合があります

//Define a lock object somewhere. Each thread must have access to this somehow. 
private final Lock lock = new ReentrantLock(); 

public void run() { 
    boolean inBase = true; 
    //This thread is about to use and modify the world. 
    //Wait for other threads to finish and occuppy the world by locking. 
    lock.lock(); 
    while (inBase) { 
     for (int cityID = 0; cityID < world.getCities().size() && inBase; cityID++) { 
      City city = world.getCities().get(cityID); 
      if (!city.getRequestsList().isEmpty()) { 
       for (int requestID = 0; requestID < city.getRequestsList().size(); requestID++) { 
        Request request = city.getRequestsList().get(requestID); 
        if (request.isRequest()) { 
         request.setRequest(false); 
         System.out.println(Thread.currentThread().getName() + " is flying to " + city.getName()); 
         inBase = false; 
         break; 
        } 
       } 
      } 
     } 
    } 
    //This thread is finished with modifying the world. 
    //Release the lock so other threads can use it. 
    lock.unlock(); 
    //Do stuff that planes do while flying. 
} 

いくつかのより多くのReentrantLockについての情報:Java ist auch eine Insel - ReentrantLock

関連する問題