簡體   English   中英

在 java 中保留 Timer.schedule 的調用堆棧

[英]Preserve call stack of, Timer.schedule in java

我有一個守護線程正在運行,只要廚師不忙並且有訂單要交付,它就會調用 function (prepareOrder)。 prepareOrder 根據完成訂單所需的時間,在一定的時間間隔后調用 orderComplete function。 現在我面臨的問題是只有對 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();
        }
    }
}

准備訂單 function。

 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);
    }

主要function驅動代碼。

orderMachine.takeNewOrder(fullMeal, "Tom");
orderMachine.takeNewOrder(halfMeal, "Bob");
daemonThread backThread = new daemonThread(orderMachine);
backThread.setDaemon(true);
backThread.assignCook();

現在對我來說只有最后下的訂單(“Bob”)被打印在 sout 上。 Timer.schedule 創建的所有調用如何保留在堆棧中。


編輯

接受新訂單 function。

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的公共倉庫

這段代碼中的問題是一個並發錯誤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");
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM