繁体   English   中英

如何在ProducerConsumer情况下停止Java线程?

[英]How to stop Java Threads in a ProducerConsumer situation?

我的代码如下所示,它具有两个Runnable类:Cook(producer)和Waiter(consumer)。

做饭的时候用餐次数少于5次
用餐人数超过0时服务员将上班。

它可以正常运行,但无法停止。
我在代码末尾放置了exec.shutdown() ,但是什么也没发生。
如果我将其替换为exec.shutdownNow() ,则在尝试睡眠时它将抛出2 InterruptedException 之后,程序仍在运行。

我该如何阻止它?
我的代码是“模拟” ProducerConsumer情况的正确方法吗?(这是我第一次尝试并发)

package com.imooc;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

class Meal {
    private final int id;

    Meal(int id) {
        this.id = id;
    }

    public String toString() {
        return "Meal: " + id;
    }
}

class Cook implements Runnable {
    private LinkedList<Meal> mealList;
    private static int count;

    Cook(LinkedList<Meal> mealList) {
        this.mealList = mealList;
    }

    public void run() {
        while (!Thread.interrupted()) {
            synchronized (mealList) {
                while (mealList.size() < 5) {
                    System.out.print("Cook is cooking meal:");
                    System.out.println(++count);
                    mealList.add(new Meal(count));
                    try {
                        TimeUnit.MILLISECONDS.sleep(200);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                mealList.notifyAll();
                while (mealList.size() == 5) {
                    System.out.println("Cook is waiting");
                    try {
                        mealList.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
        System.out.println("Cook is off-duty");
    }
}

class Waiter implements Runnable {
    private LinkedList<Meal> mealList;

    Waiter(LinkedList<Meal> mealList) {
        this.mealList = mealList;
    }

    public void run() {
        while (!Thread.interrupted()) {
            synchronized (mealList) {
                while (mealList.size() > 0) {
                    System.out.println("Waiter is taking this meal:" + mealList.getLast());
                    mealList.removeLast();
                    try {
                        TimeUnit.MILLISECONDS.sleep(200);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                mealList.notifyAll();
                while (mealList.size() == 0) {
                    System.out.println("Waiter is waiting");
                    try {
                        mealList.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
        System.out.println("Waiter is off-duty");
    }
}

public class Manager {

    public static void main(String args[]) {
        LinkedList<Meal> mealList = new LinkedList<Meal>();
        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(new Waiter(mealList));
        exec.execute(new Cook(mealList));
        exec.execute(new Waiter(mealList));
        exec.execute(new Waiter(mealList));
        exec.execute(new Cook(mealList));
        exec.shutdown();
    }

}

在此处输出屏幕截图:
在此处输入图片说明

首先, exec.shutdown()仅意味着执行者将不接受新任务。 如果要取消现有任务,则需要调用exec.shutdownNow()

其次,捕获InterruptedException重置线程的中断标志,并且while(!Thread.interrupted())将无法按预期工作。

最后,即使您在捕获到异常之后使用Thread.currentThread().interrupt()重置了中断标志,各种while条件(例如, while (mealList.size() < 5)仍然可能为假,并且您将永远循环而不到达检查中断的那条线。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM