在 java 中保留 Timer.schedule 的调用堆栈
Preserve call stack of, Timer.schedule in java
我有一个守护进程线程 运行 每当厨师不忙并且有订单要交付时,它会调用一个函数 (prepareOrder)。 prepareOrder 在一定时间间隔后调用 orderComplete 函数,具体取决于完成订单所需的时间。现在我面临的问题是只在 sout 上显示对 prepareOrder 的最后一次调用。
守护进程
package ui;
import Model.takeOrderModel;
public class daemonThread extends Thread{
//call this method in the main method of driving fucntion
private takeOrderModel orderModel;
daemonThread(takeOrderModel orderModel){
this.orderModel = orderModel;
}
public void assignCook(){
while(true){
int toComplete = orderModel.toCompleteOrders.size();
if ( !orderModel.cookBusy && toComplete>0 ) orderModel.prepareOrder();
}
}
}
准备订单功能。
public void prepareOrder(){
// pick the last element from list
if (toCompleteOrders.size() > 0){
String nextPrepare = toCompleteOrders.get(toCompleteOrders.size()-1);
order orderToComplete = allOrdersPlaced.get(nextPrepare);
completeOrder(orderToComplete);
toCompleteOrders.remove(nextPrepare);
}
}
//Helper function to prepareOrder moves an order from toComplete to prepared order
private void completeOrder(order orderToComplete){
changeCookState();
new java.util.Timer().schedule(
new java.util.TimerTask(){
@Override
public void run() {
changeCookState();
preparedOrders.add(orderToComplete.id);
deliverOrder(orderToComplete.id);
}
}, (long) (orderToComplete.timeToComplete*60)
);
}
public void changeCookState(){
this.cookBusy = !cookBusy;
}
// MODIFIES removes a order from the prepared list and puts it in delivered list
public String deliverOrder(String completedOrder){
preparedOrders.remove(completedOrder);
deliveredOrders.add(completedOrder);
System.out.println(String.format("The order of %s is here", allOrdersPlaced.get(completedOrder).customerName));
return String.format("The order of %s is here", allOrdersPlaced.get(completedOrder).customerName);
}
主函数驱动代码。
orderMachine.takeNewOrder(fullMeal, "Tom");
orderMachine.takeNewOrder(halfMeal, "Bob");
daemonThread backThread = new daemonThread(orderMachine);
backThread.setDaemon(true);
backThread.assignCook();
现在对我来说,只有最后下的订单 ("Bob") 会打印在 sout 上。 Timer.schedule 创建的所有调用如何保留在堆栈中。
编辑
接受新订单功能。
public boolean takeNewOrder(List<item> itemsInOrder, String customerName){
try {
order newOrder = new order(itemsInOrder, customerName);
allOrdersPlaced.put(newOrder.id, newOrder);
toCompleteOrders.add(newOrder.id);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
编辑 2
这里是包含完整代码的 public 仓库
https://github.com/oreanroy/Share_code_samples/tree/master/takeOrder
此代码中的问题是并发错误 - cookBusy
变量正在从两个不同的线程写入。要解决此问题,请使用 AtomicBoolean
而不是 boolean
,因为这是线程安全的。
AtomicBoolean cookBusy = new AtomicBoolean(false);
使用compareAndSet
确保共享变量在更新前设置为已知值。
public void changeCookState(boolean busy){
if (!this.cookBusy.compareAndSet(!busy, busy))
{
throw new RuntimeException("shared variable set to unexpected value");
}
}
我有一个守护进程线程 运行 每当厨师不忙并且有订单要交付时,它会调用一个函数 (prepareOrder)。 prepareOrder 在一定时间间隔后调用 orderComplete 函数,具体取决于完成订单所需的时间。现在我面临的问题是只在 sout 上显示对 prepareOrder 的最后一次调用。
守护进程
package ui;
import Model.takeOrderModel;
public class daemonThread extends Thread{
//call this method in the main method of driving fucntion
private takeOrderModel orderModel;
daemonThread(takeOrderModel orderModel){
this.orderModel = orderModel;
}
public void assignCook(){
while(true){
int toComplete = orderModel.toCompleteOrders.size();
if ( !orderModel.cookBusy && toComplete>0 ) orderModel.prepareOrder();
}
}
}
准备订单功能。
public void prepareOrder(){
// pick the last element from list
if (toCompleteOrders.size() > 0){
String nextPrepare = toCompleteOrders.get(toCompleteOrders.size()-1);
order orderToComplete = allOrdersPlaced.get(nextPrepare);
completeOrder(orderToComplete);
toCompleteOrders.remove(nextPrepare);
}
}
//Helper function to prepareOrder moves an order from toComplete to prepared order
private void completeOrder(order orderToComplete){
changeCookState();
new java.util.Timer().schedule(
new java.util.TimerTask(){
@Override
public void run() {
changeCookState();
preparedOrders.add(orderToComplete.id);
deliverOrder(orderToComplete.id);
}
}, (long) (orderToComplete.timeToComplete*60)
);
}
public void changeCookState(){
this.cookBusy = !cookBusy;
}
// MODIFIES removes a order from the prepared list and puts it in delivered list
public String deliverOrder(String completedOrder){
preparedOrders.remove(completedOrder);
deliveredOrders.add(completedOrder);
System.out.println(String.format("The order of %s is here", allOrdersPlaced.get(completedOrder).customerName));
return String.format("The order of %s is here", allOrdersPlaced.get(completedOrder).customerName);
}
主函数驱动代码。
orderMachine.takeNewOrder(fullMeal, "Tom");
orderMachine.takeNewOrder(halfMeal, "Bob");
daemonThread backThread = new daemonThread(orderMachine);
backThread.setDaemon(true);
backThread.assignCook();
现在对我来说,只有最后下的订单 ("Bob") 会打印在 sout 上。 Timer.schedule 创建的所有调用如何保留在堆栈中。
编辑
接受新订单功能。
public boolean takeNewOrder(List<item> itemsInOrder, String customerName){
try {
order newOrder = new order(itemsInOrder, customerName);
allOrdersPlaced.put(newOrder.id, newOrder);
toCompleteOrders.add(newOrder.id);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
编辑 2
这里是包含完整代码的 public 仓库 https://github.com/oreanroy/Share_code_samples/tree/master/takeOrder
此代码中的问题是并发错误 - cookBusy
变量正在从两个不同的线程写入。要解决此问题,请使用 AtomicBoolean
而不是 boolean
,因为这是线程安全的。
AtomicBoolean cookBusy = new AtomicBoolean(false);
使用compareAndSet
确保共享变量在更新前设置为已知值。
public void changeCookState(boolean busy){
if (!this.cookBusy.compareAndSet(!busy, busy))
{
throw new RuntimeException("shared variable set to unexpected value");
}
}