如何在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()
,它将在尝试睡眠时抛出2InterruptedException
。之后,程序仍在运行。我怎样才能阻止它?
我的代码是否是“模拟”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();
}
}