【问题标题】:Preserve call stack of, Timer.schedule in java在java中保留Timer.schedule的调用堆栈
【发布时间】:2020-07-21 15:59:24
【问题描述】:

我有一个守护线程正在运行,只要厨师不忙并且有订单要交付,它就会调用一个函数 (prepareOrder)。根据完成订单所需的时间,prepareOrder 在一定时间间隔后调用 orderComplete 函数。现在我面临的问题是只有对 prepareOrder 的最后一次调用才会显示在 sout 上。

守护进程

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

这里是包含完整代码的公共仓库 https://github.com/oreanroy/Share_code_samples/tree/master/takeOrder

【问题讨论】:

  • orderMachine.takeNewOrder 是做什么的?
  • 它接受一个新订单并添加到 allOrdersPlaced 和 toCompleteOrder 列表。进行编辑。

标签: java asynchronous design-patterns garbage-collection callstack


【解决方案1】:

此代码中的问题是并发错误 - 正在从两个不同的线程写入 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");
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-14
    • 2015-08-22
    • 2014-07-10
    • 2011-11-20
    • 2016-12-06
    • 2011-03-12
    • 2014-10-21
    相关资源
    最近更新 更多