Программа никогда не заканчивается, но Thread Pool утверждает, что закрывается
У меня проблема с многопоточной программой.
Мне нужно смоделировать множество людей, пытающихся забронировать один и тот же рейс одновременно, не используя замки.
Поэтому я создал 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 ответа
Когда planeIsBooked
становиться true
Похоже, что ваш самолет забронирован, никогда не будет инициализирован в true
в то время как цикл. Поэтому убедитесь, что ваш цикл не бесконечен.
Пройдите этот ответ, чтобы узнать, почему вы должны объявлять статические переменные как переменные в многопоточной среде.
Несмотря на то, что ваша статическая переменная изменчива, следующие строки опасны
while(planeIsBooked == false) {
Future<Integer> submit = pool.submit(new UserThread(id));
}
Считайте, что ваш заказ на рейс занимает в среднем 2 секунды. А у вас около 300 мест (предположение). Ваше поле planeIsBooked станет истинным через 600 секунд (если оно работает в одном потоке). При размере пула 50 он будет работать за 12 секунд.
С учетом вышеизложенного предположения ваш цикл будет работать 12 секунд. Теперь подумайте, сколько раз выполнялся оператор запроса на отправку? я раз. Несмотря на то, что у вас есть только 300 мест, вы можете дать appox больше минимальных миллионов запросов за 12 секунд.
Таким образом, подумайте о количестве заданий в очереди, прежде чем вызывать Shutdown now() . Это неправильный способ завершения цикла
Если вы знаете максимальный размер своего места в самолете, почему бы вам не использовать его в цикле for (возможно, это внешний параметр для цикла for вместо переменной для удержания
Пара вещей:
Сначала после звонка pool.shutdownNow();
- вы пытаетесь сразу же получить результаты. Вызов shutDownNow() не блокируется и не является точным указанием того, что пул остановлен. Для этого - вы должны позвонить pool.awaitTermination()
,
Во-вторых, не ясно, что вы подразумеваете под своим комментарием -
// ЗДЕСЬ, ГДЕ ОНА ПЕТЛЯЕТ
Это находится в цикле - и, глядя на цикл - если в корпусе коммутатора возникает исключение - тогда он перейдет в ловушку - проигнорируйте его и выполните цикл. Вы проверяли наличие исключений?
Первым делом while(planeIsBooked == false)
всегда оценивается как истина, потому что
planeIsBooked = false always , nowhere its initialized to true.
так почему же ваше условие while становится ложным и выходит?
установить в то время как цикл где-то planeIsBooked = true
выйти из цикла пока.