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

如何在ProducerConsumer情况下停止Java线程?,java,multithreading,concurrency,Java,Multithreading,Concurrency,我的代码如下所示,它有两个可运行类:库克(生产者)和服务员(消费者)。 厨师将在用餐次数少于5次时上班, 当用餐人数超过0时,服务员将上班。 它运行正常,但无法停止。 我在代码末尾添加了一个exec.shutdown(),但什么也没发生。 如果我将其替换为exec.shutdownNow(),它将在尝试睡眠时抛出2InterruptedException。之后,程序仍在运行。 我怎样才能阻止它? 我的代码是否是“模拟”ProducerConsumer情况的正确方法?(这是我第一次尝试并发性) p

我的代码如下所示,它有两个可运行类:库克(生产者)和服务员(消费者)。

厨师将在用餐次数少于5次时上班,
当用餐人数超过0时,服务员将上班。

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

我怎样才能阻止它?
我的代码是否是“模拟”ProducerConsumer情况的正确方法?(这是我第一次尝试并发性)

package com.imooc;
导入java.util.*;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.TimeUnit;
班级餐{
私有最终int id;
膳食(内部id){
this.id=id;
}
公共字符串toString(){
返回“餐:+id;
}
}
类Cook实现了Runnable{
私人联络人米利斯特;
私有静态整数计数;
库克(LinkedList mealList){
this.mealList=mealList;
}
公开募捐{
而(!Thread.interrupted()){
同步(mealList){
while(mealList.size()<5){
打印(“厨师正在做饭:”);
System.out.println(++计数);
添加(新餐(计数));
试一试{
时间单位。毫秒。睡眠(200);
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
mealList.notifyAll();
while(mealList.size()=5){
System.out.println(“库克正在等待”);
试一试{
等一下;
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
}
}
System.out.println(“库克下班”);
}
}
类服务员实现可运行{
私人联络人米利斯特;
服务员(LinkedList mealList){
this.mealList=mealList;
}
公开募捐{
而(!Thread.interrupted()){
同步(mealList){
while(mealList.size()>0){
System.out.println(“服务员正在吃这顿饭:+mealList.getLast());
mealList.removeLast();
试一试{
时间单位。毫秒。睡眠(200);
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
mealList.notifyAll();
while(mealList.size()==0){
System.out.println(“服务员在等”);
试一试{
等一下;
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
}
}
System.out.println(“服务员下班了”);
}
}
公共班级经理{
公共静态void main(字符串参数[]){
LinkedList mealList=新建LinkedList();
ExecutorService exec=Executors.newCachedThreadPool();
执行官(新服务员(米利斯特));
执行董事(新厨师(米利斯特));
执行官(新服务员(米利斯特));
执行官(新服务员(米利斯特));
执行董事(新厨师(米利斯特));
exec.shutdown();
}
}
此处输出屏幕截图:

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

其次,捕获
InterruptedException
会重置线程的中断标志,而(!thread.interrupted())将无法按预期工作


最后,即使在捕获异常后使用
Thread.currentThread().interrupt()
重置中断标志,各种while条件(例如
while(mealList.size()<5))也会发生变化
可能仍然是错误的,您将永远循环,而不会到达检查中断的行。

这里有类似的问题:。您需要正确终止线程。也请阅读文档:您的代码与您描述的不一样。在您的代码中,厨师总是在服务员做任何事情之前煮5顿饭。同样,厨师也会直到服务员端上5顿饭为止。在现实世界中,这会降低吞吐量,因为不管吃饭的情况如何,其中一个线程总是在等待。也许这可以帮助您:最后,我用try-catch包围run()方法来停止线程,就像Java中的思维一样。这是正确的方法吗?
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();
    }

}