结束线程

时间:2018-06-09 01:45:43

标签: java multithreading sleep notify

我试图模拟银行的服务。到目前为止,我可以随机地随机生成客户,如果他们不忙,收银员将为他们服务。当模拟应该结束时,我的问题就来了......它不会。客户不再生成,但收银员一直在等待客户。我尝试了不同的方法,但都失败了。这是尝试不同解决方案之前的代码。

这是CustomerGenerator:

    @Override
public void run() {
    while (currentTime != openTime) {
        double accept = Math.random();
        if (accept >= 0.6) {
            addCustomerToQueue();
            System.out.println("Customer in line.");
        } else {
            System.out.println("Waiting for a customer.");
        }
        try {
            currentTime += 1000;
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

private synchronized void addCustomerToQueue() {
    Customer customer = new Customer(placeInLine + 1);
    this.customerLinkedList.add(customer);
    placeInLine++;
    notify();
}

synchronized Customer getNextCustomer() throws InterruptedException {
    notify();
    while (customerLinkedList.size() == 0) {
        wait();
    }
    return customerLinkedList.poll();
}

这是收银员:

    @Override
public void run() {
    try {
        while (true) {
            Customer customer = generator.getNextCustomer();
            int customerServingNumber = customer.getServingNumber();
            double customerServingTime = customer.getServingTime();
            System.out.println(cashierName + " serving " + customerServingNumber + " for " + getServingTime(customerServingTime));
            Thread.sleep(customerServingNumber * 1000);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

3 个答案:

答案 0 :(得分:1)

Cashier线程仅在被中断后终止(在Thread.interrupt直接调用或通过ExecutorService.shutdownNow之类的其他函数调用后)。您必须安排线程被中断,如果设置了某个条件(如布尔标志)则中断,或者传入一个特殊的空对象,告诉线程自己退出。

虽然您可以使用waitnotify对此进行建模,但使用producer-consumer实施BlockingQueue工作流程更为简单。将生成器线程put元素放入队列,并从队列中获取消费者线程take。当没有更多元素要生成时,在队列中添加一个特殊的空对象,作为消费者退出的信号,或者只是中断线程。

答案 1 :(得分:1)

jspcal

所述
  

Cashier线程仅在被中断后终止(在Thread.interrupt直接调用或通过ExecutorService.shutdownNow等其他函数调用后发生。

有时 - 是的,您可以使用waitnotify来运行您的系统,或Thread.interrupt()来结束您的主题 - "停止线程" 解决此问题的方法是将Cashier主循环从while(true)更改为while(condition)。收银员接受时这种情况应该是真的,而Cashier不接受这种情况是假的。

答案 2 :(得分:0)

这很有用,但我想知道它是否是一个合适的解决方案:

CustomerGenerator:

synchronized Customer getNextCustomer() throws InterruptedException {
    notify();
    while (customerLinkedList.size() == 0) {
        if (currentTime == openTime){
            return null;
        }
        wait();
    }
    return customerLinkedList.poll();
}

收银员:

@Override
public void run() {
    try {
        Customer customer = generator.getNextCustomer();
        while (customer != null) {
            int customerServingNumber = customer.getServingNumber();
            double customerServingTime = customer.getServingTime();
            System.out.println(cashierName + " serving " + customerServingNumber + " for " + getServingTime(customerServingTime));
            customer = null;
            Thread.sleep(customerServingNumber * 1000);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}