Java多线程——简单的生产者消费者问题练习

Java多线程生产者消费者

Java的多线程学习中,因为有练习的要求,扔个生产者消费者的代码放上来:
先解释一下,里面有三个类,分别是cook(厨师),waiter(服务生)和food,厨师生产食物,而服务生则端走食物。那么先写一个用锁去同步的多线程,代码其实很简单,就是厨师对食物进行更改,直接修改食物的类型(手撕鸡或者卤猪脚),就算是食物生产完成了。


public class TestThread {
    
    

    public static void main(String[] args){
    
    
        food f = new food();
        cook c = new cook(f);
        waiter w = new waiter(f);
        Thread t1 = new Thread(c);
        Thread t2 = new Thread(w);
        t1.start();
        t2.start();
    }

}
class cook implements Runnable{
    
    
    food f;
    static final int count = 5;
    cook(food f){
    
    
        this.f = f;
    }
    @Override
    public void run() {
    
    
        for (int i = 0; i < count; i++) {
    
    
            f.l.lock();
            if(i % 2 == 0) {
    
    
                f.setName("手撕鸡");
                f.setTaste("麻辣味");
                f.setFood();
            }else{
    
    
                f.setName("卤猪脚");
                f.setTaste("卤煮味");
                f.setFood();
            }
            f.l.unlock();
            try {
    
    
                Thread.sleep(100);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

class waiter implements Runnable{
    
    
    food f;
    static final int count = 5;
    waiter(food f){
    
    
        this.f = f;
    }
    @Override
    public void run() {
    
    
        for (int i = 0; i < count; i++) {
    
    
            f.l.lock();
            f.getFood();
            f.l.unlock();
            try {
    
    
                Thread.sleep(100);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

class food{
    
    
    String name;
    String taste;
    Lock l;
    public food() {
    
    
        l = new ReentrantLock();
    }

    public void setFood(){
    
    
        System.out.println("厨师制作了" + taste + name);
    }
    public void getFood(){
    
    
        System.out.println("服务员端走了" + taste + name);
    }
    public food(String name, String taste) {
    
    
        this.name = name;
        try {
    
    
            Thread.sleep(100);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        this.taste = taste;
        l = new ReentrantLock();
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public String getTaste() {
    
    
        return taste;
    }

    public void setTaste(String taste) {
    
    
        this.taste = taste;
    }
}

那么这段代码运行的一个结果是这样的:
在这里插入图片描述
可以看到,我们虽然设置了线程同步(用的是显式锁),但是没规定是厨师先上菜还是服务员先端盘子,于是乎就出现了上图的服务员先端走了未初始化的food的情况。
鉴于课程的内容,这边就直接在food类中加一个信号量,用类似互斥锁的同步方法(其实生产者消费者问题,应该是厨师制作食物达到上限后,才沉睡,但是本问题是将一个食物反复操作,相当于上限只能是1),(厨师做完活以后就睡眠并唤醒服务员,服务员做完后也沉睡并唤醒厨师,原本是准备照着这么做的,结果我用的不是继承thread,而是继承Runnable接口,所以似乎不能这么用),那么用一个boolean信号量来做这个同步就好,代码和结果是这样的:

class cook implements Runnable{
    
    
    food f;
    static final int count = 50;
    cook(food f){
    
    
        this.f = f;
    }
    @Override
    public void run() {
    
    
        for (int i = 0; i < count; i++) {
    
    
            if(!f.flag) {
    
    
                f.l.lock();
                if (i % 2 == 0) {
    
    
                    f.setName("手撕鸡");
                    f.setTaste("麻辣味");
                    f.setFood();
                } else {
    
    
                    f.setName("卤猪脚");
                    f.setTaste("卤煮味");
                    f.setFood();
                }
                f.flag = true;
                f.l.unlock();
            }
            try {
    
    
                Thread.sleep(100);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

class waiter implements Runnable{
    
    
    food f;
    static final int count = 50;
    waiter(food f){
    
    
        this.f = f;
    }
    @Override
    public void run() {
    
    
        for (int i = 0; i < count; i++) {
    
    
            if(f.flag) {
    
    
                f.l.lock();
                f.getFood();
                f.flag = false;
                f.l.unlock();
            }
            try {
    
    
                Thread.sleep(100);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

其中,在food类里加入了一个flag,这里觉得太长就不全放上来了,其实代码的修改不多。
这个时候运行的结果就比较舒适了:
在这里插入图片描述
这就是一个简单的生产者消费者线程同步练习。

猜你喜欢

转载自blog.csdn.net/new_DYX/article/details/113172205