0

マルチスレッド プログラムで問題が発生しました。

ロックを使用せずに、同じフライトを同時に予約しようとする多くの人をシミュレートする必要があります。

そのため、ExecutorService を作成し、それを使用してスレッドをプールし、一度に多くの同時試行を実行できるようにしました。

ただし、問題は、プログラムが最後に到達し、すべての結果を出力する直前に、そこに座って永遠に実行されることです。データベースへの接続を利用する他のすべてのクラスにアクセスして、手動で閉じようとしました。運がない。

package dbassignment4;

   import java.util.ArrayList;
   import java.util.List;
   import java.util.concurrent.ExecutionException;
   import java.util.concurrent.ExecutorService;
   import java.util.concurrent.Future;
   import java.util.concurrent.LinkedBlockingQueue;
   import java.util.concurrent.RejectedExecutionException;
   import java.util.concurrent.ThreadPoolExecutor;
   import java.util.concurrent.TimeUnit;

   /**
    *
    * @author Vipar
    */
   public class Master{

   private static final int POOL_SIZE = 50;
   public static boolean planeIsBooked = false;
   /**
    * @param args the command line arguments
    */
   public static void main(String[] args) {

       int success = 0;
       int seatNotReserved = 0;
       int seatNotReservedByCustomerID = 0;
       int reservationTimeout = 0;
       int seatIsOccupied = 0;
       int misc = 0;

       HelperClass.clearAllBookings("CR9");
       Thread t = new Thread(new DBMonitor("CR9"));
       long start = System.nanoTime();
       //HelperClass.clearAllBookings("CR9");
       ExecutorService pool = new ThreadPoolExecutor(
               POOL_SIZE, POOL_SIZE,
               0L,
               TimeUnit.MILLISECONDS,
               new LinkedBlockingQueue<Runnable>(POOL_SIZE));
       int threadsStarted = 0;
       List<Future<Integer>> results = new ArrayList<>();
       long id = 1;
       t.start();
       while(planeIsBooked == false) {
           try {
           Future<Integer> submit = pool.submit(new UserThread(id));
           results.add(submit);
           } catch (RejectedExecutionException ex) {
               misc++;
               continue;
           }
           threadsStarted++;
           id++;
       }
       pool.shutdownNow();

       int count = 0;
       for(Future<Integer> i : results) {
           try {
               switch(i.get()) {
                   case 0:
                       // Success
                       success++;
                       break;
                   case -1:
                       // Seat is not Reserved
                       seatNotReserved++;
                       break;
                   case -2:
                       // Seat is not Reserved by Customer ID
                       seatNotReservedByCustomerID++;
                       break;
                   case -3:
                       // Reservation Timeout
                       reservationTimeout++;
                       break;
                   case -4:
                       // Seat is occupied
                       seatIsOccupied++;
                       break;
                   default:
                       misc++;
                       // Everything else fails
                       break;
               }
           } catch (ExecutionException | InterruptedException ex) {
               misc++;
           }
           count++;
           System.out.println("Processed Future Objects: " + count);
           // HERE IS WHERE IT LOOPS
       }

直後に実行されない残りのコードは次のとおりです。

long end = System.nanoTime();
long time = end - start;
System.out.println("Threads Started: " + threadsStarted);
System.out.println("Successful Bookings: " + success);
System.out.println("Seat Not Reserved when trying to book: " + seatNotReserved);
System.out.println("Reservations that Timed out: " + reservationTimeout);
System.out.println("Reserved by another ID when trying to book: " + seatNotReservedByCustomerID);
System.out.println("Bookings that were occupied: " + seatIsOccupied);
System.out.println("Misc Errors: " + misc);
System.out.println("Execution Time (Seconds): " + (double) (time / 1000000000));
}
}

問題を特定できますか?コードの実行が停止する場所にコメントを入れました。

4

4 に答える 4

0

planeIsBookedbecomeになると、 while ループでtrueplaneIsBooked が初期化されないように見えtrueます。したがって、ループが無限でないことを確認してください。

于 2014-05-03T19:50:14.173 に答える
0

マルチスレッド環境で静的変数を揮発性として宣言する必要がある理由については、この回答を参照してください。

あなたの static 変数は volatile ですが、次の行は危険です

while(planeIsBooked == false) {
        Future<Integer> submit = pool.submit(new UserThread(id));
   }

フライトの予約に平均 2 秒かかることを考慮してください。約 300 席あります (想定)。planeIsBooked フィールドは 600 秒後に true になります (シングル スレッドで実行されている場合)。50 サイズのプールでは、12 秒で実行されます。

上記の仮定では、ループは 12 秒実行されます。次に、submit request ステートメントが実行された回数を考えてみましょう。私回。シート数が 300 しかない場合でも、12 秒でさらに約 100 万件のリクエストを与えることができます。

したがって、 Shutdown now() を呼び出す前に、キュー内のジョブの数について考えてください。これはループを終了する正しい方法ではありません

フライト シートの最大サイズがわかっている場合は、for ループで使用しないでください (保持する変数の代わりに、for ループでパラメーターを外部化する場合があります)。

于 2014-05-03T20:19:48.237 に答える
0

いくつかのこと:

まず、呼び出した後、pool.shutdownNow(); すぐに結果を取得しようとしています。呼び出し shutDownNow() はブロックされておらず、プールが停止していることを明確に示すものではありません。そのためには、 に電話する必要がありますpool.awaitTermination()

第二に、コメントの意味が明確ではありません-

// ここがループする場所です

これはループの下にあります - そしてループを見て - switch ケースでスローされた例外がある場合 - それは catch に入ります - それを無視してループします。例外を確認しましたか?

于 2014-05-03T19:54:03.740 に答える