我遇到了多线程程序的问题。
我需要模拟很多人试图同时预订同一航班,不使用锁。
所以我创建了一个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));
}
}
你能发现问题吗?我在代码停止运行的地方放了一个注释。
答案 0 :(得分:0)
当planeIsBooked
成为true
时,看起来你的planeIsBooked永远不会在while循环中初始化为true
。所以要确保你的循环不是无限的。
答案 1 :(得分:0)
首先,while(planeIsBooked == false)
评估为true,因为
planeIsBooked = false always , nowhere its initialized to true.
那么你的while循环条件怎么会变错并出来呢?
设置内部while while while planeIsBooked = true
来自while循环。
答案 2 :(得分:0)
夫妻之事:
首先,在您致电pool.shutdownNow();
之后 - 您正在尝试立即获取结果。调用shutDownNow()没有阻塞,也不是池停止的明确指示。为此 - 您应该致电pool.awaitTermination()
。
其次,您的评论意味着什么并不清楚 -
//这里是它的地方
这是一个循环 - 并查看循环 - 如果在开关案例中抛出异常 - 那么它将进入catch - 忽略它并循环。你检查了例外吗?
答案 3 :(得分:0)
通过这个answer了解为什么你应该在多线程环境中将静态变量声明为volatile。
即使你的静态变量是易变的,下面的行也是危险的
while(planeIsBooked == false) {
Future<Integer> submit = pool.submit(new UserThread(id));
}
考虑您的预订航班平均2秒。你有大约300个席位(假设)。你的planeIsBooked字段将在600秒后变为真(如果它在单线程中运行)。 50个大小的游泳池将在12秒内完成。
通过上述假设,您的循环将运行12秒。 现在,想一想提交请求语句执行了多少时间?我次。 即使你只有300个座位,你也可以在12秒内给appox更多的请求。
因此,在调用Shutdown now()之前,请考虑队列中的作业号。这不是终止循环的正确方法
如果您知道飞行座椅的最大尺寸,为什么不在for循环中使用它(可以将参数外部化为for循环,而不是变量来保持